Range Function

edited April 2020
Recently, I am questioning how the range function works. In examples I have from Waters it seems like the range is inclusive of the boundary. For example:
`ENUM(LT([s/n],100), RANGE([s/n],100,200), GT([s/n],200))</code><code>`
In sections this means if we are less than 100 (e.g. 99.999999), if we are between 100 and 200 (e.g. 100.000000 - 200.000000, and if we are greater than 200 (e.g. 200.000001). I've used a precision of six to illustrate the point (and no calculations are being performed because, this is part of an enumerated (fc) calculation).
Now, given the above, I am trying to do something really simple. I have an average of replicate injections producing a % LC to a precision of 1 (e.g. 98.5%). I have another custom field that looks like:
`<pre class="CodeBlock"><code>RANGE(Average_LC, 98.5, 101.5)*1*1 + LT(Average_LC,98.5)*1*2`
My Average_LC is EXACTLY 98.5 and I'm generating a 0.0 value for this section of code ... this is what makes me think the RANGE function isn't exactly inclusive of the boundary ... However, when I alter the code to:
`RANGE(Average_LC, 98.4, 101.5)*1*1 + LT(Average_LC,98.5)*1*2`

The custom field will return a value of 1.0.
At the end of the day, I am concerned if I am opening the door for potential error by lowering the RANGE to 98.4 as I can't have both parts of the formula coming true and thereby lead to the generation of an erroneous result.

I had a lot of trouble with the RANGE function when coding custom fields a few years ago and like yourself, I found the examples given in various Inform slideshows and even on the Empower Help topics just added to my confusion. I have seen content in Help which is downright wrong and this leaves a bad impression on anyone looking to learn. Taking into account the final precision of your answer is very important when using this function. After a lot of digging and experimenting, I read that you must consider RANGE(X,Y), as RANGE(GT X,LTE Y) so for a CF like RANGE(Height,1000,5000), any and all values greater than 1000, be that 1001 or 1000.000000001 will be included and return a 1 on the translation table. If your value is exactly 1000, this is not GT 1000, and is therefore excluded, and the 0 translation is included.

Getting back to ROUND, which I'm very careful only to use on final reported results as it can cause an enormous margin of error when using rounded values as intermediates on the way to a final value, I pick the precision in the test method or SOP of what's required. For example, I was coding a CF called RANGE(ROUND(Amount,0),98,102) as my Amount was required to 0 decimal places and I just couldn't understand why I was getting a 0 translation for a value of 97.8 which rounds to 98. The reason was it was only looking for values greater than 98 when considered as a whole number, so 98.5 onwards. When I changed it to RANGE(ROUND(Amount,0),97,102) then I captured any values greater than 97 to 0 decimals, so 97.5 onwards.

When using the CConst for these ranges, you need to subtract the relevant lowest decimal value number that's relevant to your field so if USP Resolution needs to be 1.8 to 2.2, then RANGE(ROUND(USPResolution,-1),CConst1-0.1,CConst2) will capture the desired range when 1.8 is in CConst1 because Empower subtracts 1.8-0.1, leaving 1.7, this is your "GT" fixed value so 1.75 onwards will be captured. Same with a range of 98.00 to 102.00. Put 98 in CConst1 and the formula becomes RANGE(ROUND(USP Resolution,-2),CConst1-0.01,CConst2) ie 98-0.01, which is 97.99 and therefore captures any values greater than 97.99 which will generate 98.00 so 97.995 onwards, and so on. Of course you can always just do what you did and have it as RANGE(Custom Field, 98.45,105). Hope this clears it up.

• Hi Empower2019... That's for the very detailed response! I have verified your range function being RANGE(GT X, LTE Y) using some basic test custom fields where I could generate specific numbers and can 100% confirm that this is correct.