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

- 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
- Highlight
- 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
- Subscribe to RSS Feed
- Highlight
- 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

Maxims of Maximally Efficient SAS Programmers

All Replies

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- 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
- Subscribe to RSS Feed
- Highlight
- 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
- Subscribe to RSS Feed
- Highlight
- 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
- Subscribe to RSS Feed
- Highlight
- 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
- Subscribe to RSS Feed
- Highlight
- 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

Maxims of Maximally Efficient SAS Programmers

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- 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.