Please enable JavaScript to view this site.

A-Shell Consolidated Reference

When set, this option causes A-Shell to apply a rounding factor of .000005 (5 millionths) to the INT() and FIX() functions, and to the floating point comparison operators =, <>, <=, and >=. This fudge factor can be useful in programs that use floating point variables for dollars and cents computations without taking into proper account the fact that whenever floating point values are manipulated, they begin to accumulate tiny errors in precision. If the results of such expressions are not carefully rounded to the nearest penny, the errors can add up to the point that they become noticeable. This is particularly true with non-integers, which is why the SCALE option was invented in the original A-BASIC.

The problem of precision is inherent with all floating point numbers and affects A-Shell as well as AMOS. In fact, since A-Shell uses 64 bit floating point internally and converts back and forth to A-BASIC 48 bit format as needed, it may end up with slightly different results when you go way out to the right of the decimal point. In some cases, even though the result is more "precise" due to the higher number of bits used during computation, the greater rounding effect of 48 bit versus 64 bit representation may in some cases cause the A-Shell result to appear to be less precise than the AMOS equivalent. This difference may cause A-Shell to come up with different results than AMOS in programs that are not written to take the problems of floating point precision into account.

For example, the following test, which would appear to always be TRUE, may succeed under 48 bit floating point representation and fail under 64 bit, since the loss of precision is only apparent with the extra bits:

A = 777.77

IF (A*100) = INT(A*100) ? "EQUAL"

 

There are two ways for this statement to fail or to act differently with different levels of floating point precision. First, the actual result of A*100 may be 77776.99999999. Under the 11 digit significance of 48 bit floating point, this may be the same as 77777, but not under the 14+ digit significance of 64 bit representation. Thus INT(77776.99999999) would be 77776 rather than the expected 77777, making the test fail (by a lot.) Secondly, even if the error was on the high side (i.e. 77777.00000001) and thus didn't affect the INT() operation, the comparison would still fail in 64 bit arithmetic since 77777.00000001 <> 77777.

OPTIONS=FPROUND will eliminate both parts of the problem. First, by rounding the argument of the INT() function to the nearest integer if within .000005 of it, and second by considering two expressions equal if they are within .000005 of each other.

Note that since feature applies to <= and >= comparisons, you could have the apparently illogical result of A <= B and A > B both being true (if A was .000001 greater than B.) Any program that relied on this kind of precision probably wouldn't work reliably anyway, but it is worth noting.

Also note that the preferred way to deal with the problem of floating point representation of dollars and cents is to either use SCALE 2, or to store everything as integers, dividing by 100 only for display purposes, or if you prefer to store dollars and cents unscaled, then round your results explicitly as shown here:

A = <expression> using "#######.##"

At the very least, be wary of comparing two floating point expressions for equality, since the chance of perfect equality of two 64 bit floating point results is practically nil. Assigning the expressions to variables and then comparing the variables would at least reduce the precision to 48 bit and thus give you about the same results as you would have gotten on older computers.

To review, consider the following three cases:

X:  if <expr1> = <expr2>                 (bad idea)

 

Y:  A = <expr1> : B = <expr2>

    if A = B                             (better)

 

Z:  A = <expr1> using "#######.##"

    B = <expr2> using "#######.##"

    if A = B                             (best)

 

If you are using the form in case X: or possibly even Y:, then you may benefit from OPTIONS=FPROUND.