This is not actually a problem, it is more something curious about floating-point arithmetic on Python implementation.
Could someone explain the following behavior?
>>> 1/1e-308
1e+308
>>> 1/1e-309
inf
>>> 1/1e-323
inf
>>> 1/1e-324
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero
It seems that 1 divided by a number near to zero is inf
and if it is nearer to a ZeroDivisionError
is thrown. It seems an odd behavior.
The same output for python 2.x/3.x.
EDIT: my main question here is why we get inf
for some range and not ZeroDivisionError
assuming that python seems to consider as zero 1e-309
You can't divide by zero! If you don't specify an exception type on the except line, it will cheerfully catch all exceptions. This is generally a bad idea in production code, since it means your program will blissfully ignore unexpected errors as well as ones which the except block is actually prepared to handle.
In Python, division by zero generates the exception ZeroDivisionError: division by zero. This is because in mathematics, division by zero is undefined.
In mathematics, division by 0 is undefined. Because of this, Python will issue the above error when your code tries to accomplish this undefined expression.
An input from the user is a string by default. In order to perform mathematical operations on an input, you need to either change it to an integer or a float using int() or float() respectively.
This is related to the IEEE754 floating-point format itself, not so much Python's implementation of it.
Generally speaking, floats can represent smaller negative exponents than large positive ones, because of denormal numbers. This is where the mantissa part of the float is no longer implicitly assumed to begin with a 1, but rather describes the entire mantissa, and begins with zeroes. In case you don't know what that is, I'd suggest you read up about how floats are represented, perhaps starting here.
Because of this, when you invert a denormal number, you may end up with a positive exponent too large to represent. The computer then gives you inf
in its place. The 1e-308
in your example is actually also denormal, but still not small to overflow when inverted (because among normal numbers, the standard actually allows for slightly larger positive than negative exponents).
In case of 1e-324
, that number is simply too small to be represented even as a denormal, so that float literal is effectively equal to zero. That's why you get division by zero. The smallest representable 64-bit float is (slightly below) 5e-324
.
Minimum value that can be used as float numer in Python is :
2.2250738585072014e-308
Python uses double-precision floats, which can hold values from about 10 to the -308 to 10 to the 308 power.
Wikipedia - double precision floating point format
Actually, you can probably get numbers smaller than 1e-308 via denormals,But there is a significant performance hit to this. I found that Python is able to handle 1e-324
but underflows on 1e-325
and returns 0.0
as the value.
Most of the things have already been explained by Dolda2000 in his answer. Yet it might be helpful to see this.
>>> 1e-308
1e-308
>>> 1e-309
1e-309
>>> 1e-323
1e-323
>>> 1e-324
0.0
As you can see 1e-324
is equal to 0.0
in python implementation. As Dolda2000 put it very nicely: that number is simply too small to be represented even as a denormal, so that float literal is effectively equal to zero
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With