1

I was experimenting with the IDLE Python 3.4.0 shell, and executed the following code.

>>> from decimal import *
>>> getcontext().prec = 500
>>> e = Decimal(2.4)
>>> print(e)
2.399999999999999911182158029987476766109466552734375

As you can see, I set the variable e equal to exactly 2.4, nothing more, nothing less. However, when I printed e, instead of printing 2.4 or 2.400000..., it printed what you see above. I then tried changing the getcontext().prec to 5, and it still printed the exact same results. Now, to repeat my experiment, I tested it with a whole number, and then another decimal number.

>>> f = Decimal(10)
>>> print(f)
10
>>> g = Decimal(10.1)
>>> print(g)
10.0999999999999996447286321199499070644378662109375

The strange string of decimal numbers is only printed whenever I assign a non-whole number with the decimal class. Finally, I tested this with floating point numbers.

>>> h = float(2.4)
>>> print(h)
2.4
>>> i = float(10.1)
>>> print(i)
10.1

Why does the decimal class cause these odd strings of decimals instead of the exact number?

Dorian Dore
  • 942
  • 4
  • 15
  • 35
  • 1
    [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – Mooing Duck Mar 04 '15 at 23:15
  • 1
    You actually do encounter this with whole numbers, as long as they're over 2^53 -> 9007199254740992. floats cant hold 900719925474099*3*, but they will hold 900719925474099*4*. – Mooing Duck Mar 04 '15 at 23:16
  • Possible duplicate of [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Frames Catherine White Nov 27 '15 at 12:41

2 Answers2

2

When you pass the literal 2.4 to Decimal, you are creating a Decimal from the float 2.4. The value of the float is already approximated and there is no way for Decimal to get that "exactness" back.

To create the Decimal(2.4) exactly, you can pass a string instead

>>> from decimal import *
>>> getcontext().prec = 500
>>> e = Decimal('2.4')
>>> e
Decimal('2.4')

or use division on an Decimal derived from an integer

>>> Decimal(24)/10
Decimal('2.4')
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
1

This doesn't have to do with Python, it's just the way computers handle floating-point arithmetic.

Pretend you're trying to write down 1/3 exactly as a decimal in base 10 - you can't as you don't have an infinite amount of time or paper. (0.333333...) There are an infinite number of 3s, so any decimal representation can only ever be an approximation.

Similarly, computers can't represent some fractions with perfect precision. (since they don't have infinite memory) So in this case, the nearest the computer can get to 10.1 is 10.0999999999999996447286321199499070644378662109375. This isn't to do with the getcontext() or any other, it's becuase the computer can't store 10.1 or 2.4 completely accurately.

  • The last paragraph is just not true. Computers *can* unquestionably represent all rational (ie fractions) with finite memory. They can't do it it with IEEE Floats, but they can with other number formats, Eg with the Faction number type https://docs.python.org/2/library/fractions.html – Frames Catherine White Nov 20 '15 at 06:35