440,077 Members | 1,175 Online
Need help? Post your question and get tips & solutions from a community of 440,077 IT Pros & Developers. It's quick & easy.

# floating point glitch

 P: n/a Is this only on solaris ? Python 2.3.3 (#1, Mar 19 2004, 16:18:33) [GCC 2.95.2 19991024 (release)] on sunos5 Type "help", "copyright", "credits" or "license" for more information. a=[66.6, 333, 333, 1, 1234.5] print a.count(333), a.count(66.6), a.count('x') 2 1 0 a.append(333) print a [66.599999999999994, 333, 333, 1, 1234.5, 333] Jul 18 '05 #1
15 Replies

 P: n/a David O'Farrell writes: Is this only on solaris ? No, it's inherent in how floating point conversions work. It happens on all IEEE 754 machines. You don't need that fancy list-append stuff to see it happen. Just type 66.6 66.599999999999994 Jul 18 '05 #2

 P: n/a In article <7x************@ruckus.brouhaha.com>, Paul Rubin wrote:David O'Farrell writes: Is this only on solaris ?No, it's inherent in how floating point conversions work. It happenson all IEEE 754 machines. You don't need that fancy list-append stuffto see it happen. Just type 66.666.599999999999994 Next time someone tries to Wikify the definitive response to these FAQs (I don't feel up to it myself, this week), let me recommend mention of "Computing over the Reals: Where Turing Meets Newton" . Jul 18 '05 #3

 P: n/a David O'Farrell wrote:Is this only on solaris ? Every IEEE754 processor, every language. Python 2.3.3 (#1, Mar 19 2004, 16:18:33)[GCC 2.95.2 19991024 (release)] on sunos5Type "help", "copyright", "credits" or "license" for more information. a=[66.6, 333, 333, 1, 1234.5] print a.count(333), a.count(66.6), a.count('x')2 1 0 a.append(333) print a[66.599999999999994, 333, 333, 1, 1234.5, 333] This is a FAQ. The short answer is that 66.6 cannot be represented exactly in binary. It is an infinitely repeating fraction. (1234.5 is not, which is why the same thing didn't happen to it.) When you use print, it calls repr() to get the string representation. repr tells you the exact value, as close as possible. That value is as close as you can get to 66.6 using a 64-bit IEEE754 float. str() lies to you to make you happy: str(a[0]) 66.6 -- - Tim Roberts, ti**@probo.com Providenza & Boekelheide, Inc. Jul 18 '05 #4

 P: n/a Tim Roberts wrote: >a=[66.6, 333, 333, 1, 1234.5]>print a.count(333), a.count(66.6), a.count('x')2 1 0>a.append(333)>print a[66.599999999999994, 333, 333, 1, 1234.5, 333] This is a FAQ. The short answer is that 66.6 cannot be represented exactly in binary. It is an infinitely repeating fraction. (1234.5 is not, which is why the same thing didn't happen to it.) When you use print, it calls repr() to get the string representation. Actually, print essentialy uses str() to get the string representation. But repr(list) or str(list) still gets the repr() of each item of the list rather than the str(): class TestObject(object): .... def __str__(self): .... return "" .... def __repr__(self): .... return "" .... t = TestObject() str(t) '' repr(t) '' print t t l = [TestObject()] str(l) '[]' repr(l) '[]' print l [] l [] One way around this is to call str for each item yourself: "[%s]" % ", ".join(map(str, l)) '[]' You could also define a list subclass that does this for you. -- Michael Hoffman Jul 18 '05 #5

 P: n/a Michael Hoffman writes: Actually, print essentialy uses str() to get the string representation. But repr(list) or str(list) still gets the repr() of each item of the list rather than the str(): print .66 0.66 print [.66] [0.66000000000000003] Yucch! Also, str is not invertible: a=.66 b=a+1e-16 a==b False str(a) '0.66' str(b) '0.66' Jul 18 '05 #6

 P: n/a Paul Rubin wrote: Michael Hoffman writes: Actually, print essentialy uses str() to get the string representation. But repr(list) or str(list) still gets the repr() of each item of the list rather than the str(): >>> print .66 0.66 >>> print [.66] [0.66000000000000003]Yucch! Also, str is not invertible: Right! That's the point. str() is the perfect solution in those cases where you want the language to lie to you. In many cases, that IS what you want. repr() is the perfect solution when you need an invertible function. And that's really the lesson that needs to be taught when this FAQ is A-ed. -- - Tim Roberts, ti**@probo.com Providenza & Boekelheide, Inc. Jul 18 '05 #7

 P: n/a On Mon, 27 Sep 2004 23:21:12 -0700, Tim Roberts wrote: Paul Rubin wrote: Michael Hoffman writes: Actually, print essentialy uses str() to get the string representation. But repr(list) or str(list) still gets the repr() of each item of the list rather than the str(): >>> print .66 0.66 >>> print [.66] [0.66000000000000003] Yucch! Also, str is not invertible: Right! That's the point. str() is the perfect solution in those cases where you want the language to lie to you. In many cases, that IS what you want. repr() is the perfect solution when you need an invertible function. The "perfect solution" is either: (a) to print the minimal number of digits that can maintain print/read consistency -- in this case, that means printing "0.66", or (b) to print the actual, exact, decimal representation of the value -- in this case, that means printing "0.66000000000000003108624468950438313186168670654 296875" And I think (a) is more perfect than (b) :-) -- Malum est consilium quod mutari non potest -- Publilius Syrus (setq reply-to (concatenate 'string "Paul Foley " "")) Jul 18 '05 #8

 P: n/a Paul Foley writes: The "perfect solution" is either: (a) to print the minimal number of digits that can maintain print/read consistency -- in this case, that means printing "0.66", Nah, you can do that by printing everything as zero. Jul 18 '05 #9

 P: n/a >>>>> Paul Rubin (PR) wrote: PR> Paul Foley writes: The "perfect solution" is either: (a) to print the minimal number of digits that can maintain print/read consistency -- in this case, that means printing "0.66", PR> Nah, you can do that by printing everything as zero. That would not maintain print/read consistency, i.e. if you read back the printed value you don't get the original value. -- Piet van Oostrum URL: http://www.cs.uu.nl/~piet [PGP] Private email: P.***********@hccnet.nl Jul 18 '05 #10

 P: n/a Piet van Oostrum writes: PR> Nah, you can do that by printing everything as zero. That would not maintain print/read consistency, i.e. if you read back the printed value you don't get the original value. The current conversion doesn't have that property. a=.66+1e-13 print a 0.66 b=0.66 a==b False Jul 18 '05 #11

 P: n/a >>>>> Paul Rubin (PR) wrote: PR> Piet van Oostrum writes: PR> Nah, you can do that by printing everything as zero. That would not maintain print/read consistency, i.e. if you read back the printed value you don't get the original value. PR> The current conversion doesn't have that property. a=.66+1e-13 print a PR> 0.66 b=0.66 a==b PR> False That's because print uses str rather than repr: a=.66+1e-13 a 0.66000000000010006 print `a` 0.66000000000010006 b=0.66000000000010006 a==b True -- Piet van Oostrum URL: http://www.cs.uu.nl/~piet [PGP] Private email: P.***********@hccnet.nl Jul 18 '05 #12

 P: n/a Tim Roberts wrote: Right! That's the point. str() is the perfect solution in those cases where you want the language to lie to you. In many cases, that IS what you want. repr() is the perfect solution when you need an invertible function. repr() does not provide an invertible function if you are using it on a list, as was pointed out here, since list.__repr__() essentially calls str() for its float members rather than repr(). -- Michael Hoffman Jul 18 '05 #13

 P: n/a Michael Hoffman wrote: Tim Roberts wrote: Right! That's the point. str() is the perfect solution in those cases where you want the language to lie to you. In many cases, that IS what you want. repr() is the perfect solution when you need an invertible function. repr() does not provide an invertible function if you are using it on a list, as was pointed out here, since list.__repr__() essentially calls str() for its float members rather than repr(). It does? [0.66] [0.66000000000000003] repr([0.66]) [0.66000000000000003]' str([0.66]) [0.66000000000000003]' str(0.66) '0.66' repr(0.66) '0.66000000000000003' -Peter Jul 18 '05 #14

 P: n/a Michael Hoffman wrote: Tim Roberts wrote: Right! That's the point. str() is the perfect solution in those cases where you want the language to lie to you. In many cases, that IS what you want. repr() is the perfect solution when you need an invertible function. repr() does not provide an invertible function if you are using it on a list, as was pointed out here, since list.__repr__() essentially calls str() for its float members rather than repr(). ?! I think you're confused, since things are exactly the other way around: list.__str__ calls repr on its members (so does list.__repr__, which happens to be exactly the same function). repr isn't necessarily perfect in all cases, but it does do a creditable job on many built-in types -- including all kinds of built-in numbers, strings, and containers whose leaves are such numbers and strings. Alex Jul 18 '05 #15

 P: n/a Alex Martelli wrote: Michael Hoffman wrote:repr() does not provide an invertible function if you are using it on alist, as was pointed out here, since list.__repr__() essentially callsstr() for its float members rather than repr(). ?! I think you're confused, since things are exactly the other way around: list.__str__ calls repr on its members (so does list.__repr__, which happens to be exactly the same function). Yep, I got that exactly backwards. D'oh! Thanks Alex and I'm sorry for any confusion I caused. -- Michael Hoffman Jul 18 '05 #16

### This discussion thread is closed

Replies have been disabled for this discussion.