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
- /
- Adding floating-point numbers

Topic Options

- 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
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

08-16-2016 06:31 AM

I am trying to understand how floating-point numbers are added in SAS. I have the following code:

data data1;

format b c d binary64.;

b=0.5; c=0.3; d=b+c;

if d=0.8 then flag=1;

RUN;

And flag is really set to 1.

In binary64:

b=0011111111100000000000000000000000000000000000000000000000000000

c=0011111111010011001100110011001100110011001100110011001100110011

d=0011111111101001100110011001100110011001100110011001100110011010

and 0.8 is represented the same as d. My problem is that when I try to add b and c, normalize the mantissas and add bit by bit I get a number that differs from d. I checked all my calculations and this is not the case. Does anyone know why this can happen?

Accepted Solutions

Solution

08-16-2016
08:45 AM

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

Posted in reply to Yuliia

08-16-2016 08:20 AM

Keep in mind that 52 bits are stored, but the precision is actually 53 bits (there's always a "hidden" 1 at the beginning of the mantissa) and the math unit in the CPU can probably use all it's 64 integer bits for adding.

So your CPU adds

10000000000000000000000000000000000000000000000000000

+ 010011001100110011001100110011001100110011001100110011 = 110011001100110011001100110011001100110011001100110011

Before you store that back, the leading 1 is eliminated, the exponent once again set to -1, and the 53rd bit from the remaining number is rounded to the 52nd, which is also 1, so the 51st is set to 1 and the 52nd to 0.

---------------------------------------------------------------------------------------------

Maxims of Maximally Efficient SAS Programmers

How to convert datasets to data steps

How to post code

Maxims of Maximally Efficient SAS Programmers

How to convert datasets to data steps

How to post code

All Replies

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

Posted in reply to Yuliia

08-16-2016 07:15 AM

You should use round() around calculated floating point. There is a quirk in machines - can't remember the exact term, where a number can have a very small amount on the end of the number, e.g. 0.80000000000000001, but SAS does not display that. If you apply the round() to this it will return exactly the number:

if round(d,.1)=0.8 then flag=1;

you will see this a fair bit in proc sompare ouputs, where it shows differences in numbers which you cant see. Just make sure to round your values to the correct decimal places.

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

08-16-2016 07:52 AM - edited 08-16-2016 07:54 AM

Thanks for the tip. When I perform the comparison 0.5+0.3 does equal 0.8, however when I actually try to repeat what SAS does in the way I understand it I can't. I get a different value, not 0011111111101001100110011001100110011001100110011001100110011010

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

Posted in reply to Yuliia

08-16-2016 07:44 AM

There is a thorough discussion on the topic in the SAS online docs called Numerical Accuracy in SAS Software. In my view a must-read for every SAS user.

Regards,

- Jan.

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

Posted in reply to jklaverstijn

08-16-2016 07:48 AM

Hi Jan, I've seen this and I am trying to repeat the process the same way in my understanding SAS would do it: i.e. adjust the mantissas, truncate afterwards but probably I am missing something as for this example I am not able to recreate the values. However if I take 0.7 and 0.1 and do the same I can recreate the values and see that 0.7+0.1 is not equal to 0.8

Solution

08-16-2016
08:45 AM

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

Posted in reply to Yuliia

08-16-2016 08:20 AM

Keep in mind that 52 bits are stored, but the precision is actually 53 bits (there's always a "hidden" 1 at the beginning of the mantissa) and the math unit in the CPU can probably use all it's 64 integer bits for adding.

So your CPU adds

10000000000000000000000000000000000000000000000000000

+ 010011001100110011001100110011001100110011001100110011 = 110011001100110011001100110011001100110011001100110011

Before you store that back, the leading 1 is eliminated, the exponent once again set to -1, and the 53rd bit from the remaining number is rounded to the 52nd, which is also 1, so the 51st is set to 1 and the 52nd to 0.

---------------------------------------------------------------------------------------------

Maxims of Maximally Efficient SAS Programmers

How to convert datasets to data steps

How to post code

Maxims of Maximally Efficient SAS Programmers

How to convert datasets to data steps

How to post code

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

Posted in reply to KurtBremser

08-16-2016 08:45 AM

Thanks so much! I forgot about the rounding. Now everything is pretty clear.