turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

Find a Community

- Home
- /
- SAS Programming
- /
- Base SAS Programming
- /
- decimal places Calculaitons

Topic Options

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

12-04-2015 04:58 AM

Hi

x = 0.3

y = 0.1 + 0.1 + 0.1

if x = y then z = "Same values"

else z = "Not"

still z = "Not".

Why is that ??? Please help

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to vandhan

12-04-2015 05:25 AM

Hi,
SAS thinks x & y values are not equal if calculated as per your code, it is because of the precision which takes into account.
data _null_ ;
x = 0.3 ;
y = 0.1 + 0.1 + 0.1 ;
d = x - y ;
if x = y then do ;
z = "Same values" ;
end ;
else z = "Not" ;
put x y z d ;
run ;
Log: 0.3 0.3 Not 1.387779E-17
the difference is not 0 so as per SAS x & y values are not equal

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to vandhan

12-04-2015 05:26 AM

This is a general thing with decimals. I can't remember the exact terminology for it, but the underlying number is stored with a very tiny part of the number, so you may be comparing 0.3 to 0.3000000000000001, which is different. This is down to the memory storgae of the number and you will come across it a bit. I would always recommend, unless you need to leave a raw number, to round to a know decimal value to omit these kind of problems:

data have; x = 0.3; y = 0.1 + 0.1 + 0.1; if round(x,.1)=round(y,.1) then z="same"; else z="not"; run;

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to vandhan

12-04-2015 06:21 AM - edited 12-04-2015 06:22 AM

You have encountered a numeric representation issue. Roughly speaking, numeric values are stored in the binary system in the computer's memory, not in the familiar decimal system.

In your example:

0.1 (decimal) = 0.00011001100110011... (binary)

Note that the binary value is a periodic fraction. For an exact representation the "0011" would need to be repeated infinitely many times, like the 3s in 1/3=0.3333... in the decimal system. Since there are only finitely many bits available to store that value (64 bits on Windows, provided that the numeric variable is stored with the default length of 8 Bytes), the computer has no other choice but to round or truncate the infinite sequence of binary digits. But this produces a small rounding error, a numeric representation error. For the decimal number 0.1 this error is 0.4*2^-56 (on Windows), which is approx. 5.55*10^-18. Very small, but, as you know, rounding errors can accumulate easily in calculations and thus lead to surprising results, like 0.1+0.1+0.1 ne 0.3.

If you want to see how your numeric values are stored internally, use the BINARY64. or (for a shorter, but equivalent output in hexacedimal notation) HEX16. format (and **not** something like 32.30 or BEST32. format):

```
data _null_;
x=0.3;
y=0.1+0.1+0.1;
put x binary64.;
put y binary64.;
put x hex16.;
put y hex16.;
run;
```

Result:

0011111111010011001100110011001100110011001100110011001100110011 0011111111010011001100110011001100110011001100110011001100110100 3FD3333333333333 3FD3333333333334

There you see the difference in the least significant bit.

Indeed, as @RW9 has suggested, rounding is probably the most important strategy to avoid these errors. The appropriate rounding unit depends on the order of magnitude of the numbers to be rounded, but for most practical applications (i.e., if you're dealing with numbers from, say, 0.000001 to 1000000) I found 10^-9 (1E-9) to be suitable.

If you want to dig deeper into the technical details, you could read one of the two standard references on this subject:

- SAS Technical support document TS-230 "Dealing with Numeric Representation Error in SAS Applications...
- SAS Technical support document TS-654 "Numeric Precision 101"

Conference papers about this topic include:

- Shaoji Xu (2008). Is .1+.2 equal to .3?, NESUG 2008 Proceedings
- Nigel Montgomery (2008). Floating Point error – what, why and how to!!, PhUSE 2008 Proceedings
- Clarke Thacher (2011). Why .1 + .1 Might Not Equal .2 and Other Pitfalls of Floating-Point Arithmeti...

I have given talks about this subject several times in one of my projects in the past and could tell you much more. So, please don't hesitate to ask further questions about it.

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to FreelanceReinhard

12-04-2015 09:10 AM

I've experienced similar issues and have solved with the rounding function. Working for the banking industry, financial calculations we perform requires the decimal rounding function even while doing proc compares to provide the tolerances to flag as differences when exceeded.

Kannan Deivasigamani

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to vandhan

12-04-2015 09:58 PM

Besides of rounding you can also use the compfuzz() function for such situations.

Alternatively - and what I would do - you round the result of such operations from the very beginning. Something like:

y = round(0.1 + 0.1 + 0.1,0.00000001);