Hi @twedwards and @FoxHope,
Thank you for providing evidence that this phenomenon still occurs with recent SAS versions. I observed it in May 2012 when I worked on a freelance project at a pharma company. My documentation indicates that it occurred with SAS 9.2 TS2M3 on their Windows 2008 server, but not on their Unix server. Interestingly, that Windows Server 2008 was a 32-bit operating system (the "W32_SRV08 platform"), which might be crucial for this issue.
Here is an example that I documented back then:
data test;
a=0.1; b=0.7; c=a+b; d=0.8; e=d-c; f=d-c;
proc print;
run;
Result (from May 2012):
Obs A B C D E F
1 0.1 0.7 0.8 0.8 8.3267E-17 1.1102E-16
As in your examples, it was always only the first of two or more identical calculations which had an unexpected result. The result in variable F was the expected "classic numeric precision" issue, a rounding error in the least significant bit, which can be explained in detail by performing the calculation in the binary system according to the IEEE 754 standard. Only the result in E was surprising. (One of the striking consequences of the issue was that, after defining
a=0.1; b=0.7; c=a+b; d=0.8;
the seemingly exhaustive IF condition
d-c>1e-16 | d-c<1e-16 | d-c=1e-16
was not met, presumably because the result of d-c changed from 8.3267E-17 in the first part to 1.1102E-16 in the second and third part of the Boolean expression!)
Today, my SAS 9.4M5 on a 64-bit Windows workstation yields 1.1102E-16 in both variables, E and F, as expected. Similarly, it yields correctly 0 in your examples.
I agree with you and @Quentin that this looks very much like what is described in the Usage Note 6214 (which I wasn't aware of back in 2012) linked by @Kathryn_SAS.
A strong indication that it has to do with those "12 extra bits for the mantissa" (in FPU registers or somewhere else in the processor) mentioned in that Usage Note is this: The least significant bit of the internal 64-bit floating-point representation of 1/3 in a numeric variable (under Windows or Unix, including 32-bit platforms) has a place value of 2**-54=5.5511...E-17. Therefore, any "classic" numeric precision issue involving numbers close to 1/3 (namely >=0.25 and <0.5) can only create differences which are integer multiples of 2**-54. The absolute value of your example difference r=-1.8513E-17, however, is obviously less than that. In fact, it is close to one third of 2**-54 (1.85037...E-17) and an internal binary representation of it would require at least 11 additional mantissa bits: -683*2**-65 = -1.85127520951899882...E-17.
I would be curious if your difference r in BEST32. format looks like -1.851275209519E-17 and, even more precisely, like BC75580000000000 in HEX16. format.
... View more