0
votes

I can't believe I have never had this issue before (nor can I find anyone else with the same issue) but today I have just discovered that SAS sometimes gets simple calculations wrong!?! I noticed that one of my records wasn't getting picked up in the right group based on a value being <3.6 and thought there must be something strange in my data with decimal places. But on investigation I found it was just because SAS was calculating the value wrong! For some reason that I can't fathom, it seems that SAS calculates 90 - 86.4 as 3.59999999999999!!! Simple program below to show this:

code output

If I alter the calculation to 10 - 6.4 I get the correct value of 3.6000 but for some reason this one is coming out wrong. Could there be some mad setting that is wrong in my installation? I tried both SAS EG and Base SAS and both have the same issue. I feel like I'm going mad! Any help appreciated.

Thanks.

2
Your discovery is an unfortunate but expected situation related to double precision representation of numeric values. Double precision can achieve 15 or 16 decimal places of precision. Topic has been discussed here and in many other venues. Other languages have other representations such as BigDecimal class that can ameliorate some of the 'not exact' arithmetic situations that occur when using double precision. Finally, try SAS ROUND function, it can help in many cases when plain math is itty bitty off.Richard
Hi - in the future can you please try to remember to put code and output not as pictures, but as text? Thanks!Joe
Ah yes, the moment every programmer encounters! One of the best explanations on this phenomenon is by Tom Scott: youtube.com/watch?v=PZRI1IfStY0Stu Sztukowski
Thanks, that video is very interesting, good to know! Thanks for the help all, sorry about the picturesSteph DP

2 Answers

1
votes

Floating point arithmetic, in any language, will have this same issue. The same issue is possible to understand in human terms, assuming the human doesn't have a concept of infinite. If you only write down 4 digits for your decimals, for example, then:

1 - (1/3) - (1/3) - (1/3)

That's zero, right?

1 - 0.3333 = 0.6667
0.6667 - 0.3333 = 0.3334
0.3334 - 0.3333 = 0.0001

Nope! Computers do the same thing, but in binary, so they have a different (and larger) set of "problem" numbers. 1/10, for example, is not representable in binary - so adding or subtracting 0.1 is not always a "neat" operation like it is in decimal.

SAS uses 8 byte floating points, and so it gets ~15 digits of accuracy. Assuming you're not working in a field where 15 digits of accuracy is needed, you should simply round.

if round(value,.01) ge 3.6 then ... ;

Most of the time this isn't needed, but strictly speaking you should always compare rounded numbers whenever using floating point numbers (as SAS does). Integers are safe, but if you're working with 0.1 etc., use ROUND or FUZZ for integers.

-1
votes

Sorry Cannot replicate your findings.

data x;
a=90-86.4;
run;

Gives the correct result. Are you using any formats or put function. Share the complete code.