5

I apologize for the really simple and dumb question; however, why is there a difference in precision displayed for these two cases?

1)

>> test = numpy.array([0.22])
>> test2 = test[0] * 2
>> test2
0.44

2)

>> test = numpy.array([0.24])
>> test2 = test[0] * 2
>> test2
0.47999999999999998

I'm using python2.6.6 on 64-bit linux. Thank you in advance for your help.

This also hold seems to hold for a list in python

>>> t = [0.22]
>>> t
[0.22]

>>> t = [0.24]
>>> t
[0.23999999999999999]
Eric
  • 61
  • 1
  • 1
  • 3
  • 2
    That's how floats work - "in mysterious ways" ;). Dupe of so many questions I can't settle for one. –  Mar 01 '11 at 21:07
  • 1
    I wouldn't call this a duplicate of anything, since the answer is very specific to Python (plus it's my answer :) ). – Zooba Mar 01 '11 at 21:45

1 Answers1

6

Because they are different numbers and different numbers have different rounding effects.

(Practically any of the Related questions down the right-hand side will explain the cause of the rounding effects themselves.)


Okay, more serious answer. It appears that numpy performs some transformation or calculation on the numbers in an array:

>>> t = numpy.array([0.22])
>>> t[0]
0.22


>>> t = numpy.array([0.24])
>>> t[0]
0.23999999999999999

whereas Python doesn't automatically do this:

>>> t = 0.22
>>> t
0.22

>>> t = 0.24
>>> t
0.24

The rounding error is less than numpy's "eps" value for float, which implies that it should be treated as equal (and in fact, it is):

>>> abs(numpy.array([0.24])[0] - 0.24) < numpy.finfo(float).eps
True

>>> numpy.array([0.24])[0] == 0.24
True

But the reason that Python displays it as '0.24' and numpy doesn't is because Python's default float.__repr__ method uses lower precision (which, IIRC, was a pretty recent change):

>>> str(numpy.array([0.24])[0])
0.24

>>> '%0.17f' % 0.24
'0.23999999999999999'
Zooba
  • 11,221
  • 3
  • 37
  • 40
  • Weird... Python floats are C doubles though, so there shouldn't be any difference. Unless NumPy uses single precision (C floats) for some weird reason. –  Mar 01 '11 at 21:14
  • 1
    Even without Numpy it seems that python does the same thing if the value is in a list '>>> t = [0.22]' '>>> t' '[0.22]' '>>> t = [0.24]' '>>> t' '[0.239999999]' – Eric Mar 01 '11 at 21:16
  • 2
    @Eric I didn't see that effect when I tried it, but the answer is certainly that `numpy.float64.__repr__` uses a high precision in `'%0.#f'` than Python's `float.__repr__`. (Which is now in my answer.) – Zooba Mar 01 '11 at 21:22
  • Also, issues regarding the string-version display of floating points have been addressed in more recent versions of pythons, not the underlying representations, but how they show up when you print them, so it is less likely this kind of issue would be apparent. – Kevin Dolan Mar 01 '11 at 21:32
  • @Eric Under Python 2.6.6 I do get the same behaviour (`>>> 2.4` `2.33333...`) so it must have been between 2.6 and 2.7 where `float.__repr__` changed. I'm sure the changelogs will show it, but IIRC it was to prevent this sort of confusion/question. – Zooba Mar 01 '11 at 21:44