By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,077 Members | 1,175 Online
Bytes IT Community
+ Ask a Question
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
Share this Question
Share on Google+
15 Replies


P: n/a
David O'Farrell <Da************@ericsson.com> 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 <http://ph****@NOSPAM.invalid> wrote:
David O'Farrell <Da************@ericsson.com> 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


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"
<URL: http://www.ams.org/notices/200409/fea-blum.pdf >.
Jul 18 '05 #3

P: n/a
David O'Farrell <Da************@ericsson.com> 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 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]


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 "<str() called>"
.... def __repr__(self):
.... return "<repr() called>"
.... t = TestObject()
str(t) '<str() called>' repr(t) '<repr() called>' print t <str() called> t <repr() called> l = [TestObject()]
str(l) '[<repr() called>]' repr(l) '[<repr() called>]' print l [<repr() called>] l [<repr() called>]

One way around this is to call str for each item yourself:
"[%s]" % ", ".join(map(str, l))

'[<str() called>]'

You could also define a list subclass that does this for you.
--
Michael Hoffman
Jul 18 '05 #5

P: n/a
Michael Hoffman <m.*********************************@example.com > 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 <http://ph****@NOSPAM.invalid> wrote:
Michael Hoffman <m.*********************************@example.com > 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 <http://ph****@NOSPAM.invalid> wrote:
Michael Hoffman <m.*********************************@example.com > 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 " "<mycroft" '(#\@) "actrix.gen.nz>"))
Jul 18 '05 #8

P: n/a
Paul Foley <se*@below.invalid> 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 <http://ph****@NOSPAM.invalid> (PR) wrote:

PR> Paul Foley <se*@below.invalid> 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 <pi**@cs.uu.nl>
URL: http://www.cs.uu.nl/~piet [PGP]
Private email: P.***********@hccnet.nl
Jul 18 '05 #10

P: n/a
Piet van Oostrum <pi**@cs.uu.nl> 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 <http://ph****@NOSPAM.invalid> (PR) wrote:

PR> Piet van Oostrum <pi**@cs.uu.nl> 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 <pi**@cs.uu.nl>
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 <m.*********************************@example.com > 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 <m.*********************************@example.com > wrote:

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).


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.