Leo Schmidt-Traub
Leo Schmidt-Traub

Reputation: 31

Unusual python division results

I entered the following code into the python Shell:

>>>1/10**323
1e-323
>>>1/10**324
0.0

As you can see the result is unexpected. Does anybody know why this happens or how to change this? Furthermore, I also got this error:

>>> 1/10**323.1
Traceback (most recent call last):
  File "<pyshell#21>", line 1, in <module>
    1/10**323.1
OverflowError: (34, 'Result too large')

Any input would be much appreciated.

Upvotes: 0

Views: 64

Answers (1)

Jasmijn
Jasmijn

Reputation: 10477

Those problems stem directly from floating point numbers, and more precisely from IEEE 754, which is the standard implemented in most commonly used hardware and most software uses.

Python float is a double precision IEEE 754 floating point number type, which means that it stores all numbers of type float using exactly 8 bytes, which is 64 bits. 1 bit is used to store if the number is positive or negative, 11 bits are used for the exponent (the part after the e in scientific notation), and 53 bits are used for significand (the part before the e).

The real value of 1/10**324 is so close to zero that a 64 bit floating point cannot represent it. There's almost always some error in making floating point calculations, which is unavoidable, but when you're so close to zero it's much more noticeable!

That error is not because of the division. You'd get the same error with 10**323.1 or even 10**323.0.

Python integers are variable sized, you can make larger and larger numbers which take up more and more bytes to store. This means that integer operations (like 10**324) don't overflow. But if you use int ** float, the result likely won't be an integer number, so you'll have to store it in a float. And exponentiation of large numbers easily gets you to a number that doesn't fit in 64 bits any more. What do you do? Well, there are two options:

  1. Use the largest possible value, which gets labelled Infinity in the standard. This is what JavaScript does.
  2. Be cautious and prevent the programmer from making mistakes. What mistakes? Well, 10 ** 500 / 10 ** 499 should be 10 but if 10 ** 500 evaluates to Infinity and so does 10 ** 499, you'll end up with Infinity / Infinity which is indeterminate and can either error or give a special answer (called NaN for "not a number"), but you're not gonna get your 10 back.

In Python 2, int / int used to be what now is int // int, which means that 5 / 2 used to be 2. In Python 3, this was corrected. The result of division is so often not an integer in practice, that it made more sense to treat it just like float / float. As a side effect, 4 / 2 is now 2.0 instead of 2.

Upvotes: 2

Related Questions