Ask Your Question
2

rounding bug?

asked 2011-03-01 22:28:02 +0200

araichev gravatar image

updated 2011-03-01 22:32:40 +0200

Hi all:

In a notebook window i tell Sage

w = 0.4 
while w > 0.1:    
    w = w - 0.1 
    print w 
print w==0

and it outputs

0.3000000000000000
0.200000000000000
0.100000000000000
2.77555756156289e-17
False

Is this supposed to happen?

Thanks for your attention. Alex

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
3

answered 2011-03-01 23:14:39 +0200

DSM gravatar image

updated 2011-03-01 23:20:28 +0200

Yep, that's actually what's supposed to happen, because of how floating-point arithmetic works. Here's a gentle guide to the issues. Using comparisons with the results of arithmetic operations is always a bit dangerous because of limited precision.. note that the final error you get is ~2^(-55).

Your number "0.1" is living in the Real Field with 53 bits of precision:

sage: w = 0.4
sage: w
0.400000000000000
sage: parent(w)
Real Field with 53 bits of precision

and so the number isn't actually exactly 0.4:

sage: (0.4).str(base=2)
'0.011001100110011001100110011001100110011001100110011010'

You can round the result to a given number of decimal digits if you want:

sage: w = 0.4
sage: dw = 0.1
sage: ((((w - dw)-dw)-dw)-dw)
2.77555756156289e-17
sage: round(((((w - dw)-dw)-dw)-dw), ndigits=10)
0.0

Or use more precision:

sage: RF = RealField(100)
sage: RF 
Real Field with 100 bits of precision
sage: w = RF("0.4")
sage: w.str(base=2)
'0.01100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001101'
sage: dw = RF("0.1")
sage: while w > dw:    
....:         w = w - dw 
....:     print w 
....: 
0.30000000000000000000000000000
0.20000000000000000000000000000
0.10000000000000000000000000000
1.9721522630525295135293214132e-31
sage: print w==0
False

but that will only make the error smaller, in this case ~2^(-102), not vanish. You can use the Real Interval Field if you want to more accurately keep track of these differences:

sage: w = RIF("0.4")
sage: dw = RIF("0.1")
sage: while w > dw:    
....:         w = w - dw 
....:     print w 
....: 
0.3000000000000000?
0.2000000000000000?
0.1000000000000000?

where the question mark indicates uncertainty. But now the loop doesn't go all the way down to zero, because on the last step of the loop it's no longer true that 0.10000.. > 0.10000.. (See what I mean about trouble comparing?) Once you get two zeros, though, you can compare them:

sage: w = RIF("0.4")
sage: dw = RIF("0.1")
sage: ((((w - dw)-dw)-dw)-dw)
0.?e-16
sage: z = ((((w - dw)-dw)-dw)-dw)
sage: z == 0 # it's not _equal_ to 0, but:
False
sage: 0 in z # 0 is in the interval!
True

And if you really want 4/10, and not a floating-point approximation to it, you can work with the exact values:

sage: w = 4/10
sage: dw = 1/10
sage: while w >= dw:    
....:         w = w - dw 
....:     print w 
....: 
3/10
1/5
1/10
0
sage: w == 0
True

and avoid precision issues. Does that make sense?

edit flag offensive delete link more

Comments

I think you are just more comprehensive than I am :)

kcrisman gravatar imagekcrisman ( 2011-03-01 23:28:57 +0200 )edit
2

answered 2011-03-01 23:03:16 +0200

kcrisman gravatar image

In a word, yes. You are using floating point accuracy, which means that 0.4 is not actually 0.4, but rather the closest the computer can get to it with a certain accuracy. In Sage, that default is 53 bits of precision:

sage: w.parent()
Real Field with 53 bits of precision
sage: w.str(truncate=False)
'0.40000000000000002'

For what you are looking for, you need arbitrary precision - which rationals would give you.

sage: w = 4/10
sage: while w > 1/10:
....:     w = w - 1/10
....:     print w
....: 
3/10
1/5
1/10

which also shows that your loop 'should have' ended earlier, but didn't because the number that printed 0.10000 actually was slightly larger than 0.1 in the computer's internal memory, so the loop iterated one more time.

I'm not an expert on numerical analysis or machine representation of numbers, but the Internet should have some good explanations of these things.

edit flag offensive delete link more

Comments

As a further comment, pretty much any computer mathematics software is going to have this limitation. Some have only this type of representation, while others have both exact and various precision number types.

kcrisman gravatar imagekcrisman ( 2011-03-01 23:05:02 +0200 )edit

@kcrisman: I promise I didn't see yours before writing mine, so any similarity is merely driven by the subject matter. :^)

DSM gravatar imageDSM ( 2011-03-01 23:17:45 +0200 )edit

Obviously! I've actually learned quite a bit by reading up on this over the past year or so; it's very interesting. Not as good as algebra, but at least numerical analysis has some redeeming value after all.

kcrisman gravatar imagekcrisman ( 2011-03-01 23:30:16 +0200 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2011-03-01 22:28:02 +0200

Seen: 685 times

Last updated: Mar 01 '11