As mathematical concepts, I am well aware of what inf
and nan
actually are. But what I am really interested in is how they are implemented in programming languages.
In python, I can use inf
and nan
in arithmetic and conditional expressions, like this:
>>> nan = float('nan')
>>> inf = float('inf')
>>> 1 + inf
inf
>>> inf + inf
inf
>>> inf - inf
nan
This would lead me to believe that python internally has a special reserved bit sequence for these two mathematical quantities, and no other number can assume these positions. Is my assumption correct? Can you please enlighten me in this regard?
If my assumption is correct, then this can be explained easily:
>>> inf == inf
True
However, this is not:
>>> nan == nan
False
Obviously, in mathematics, this is the right answer. But how does python know that it should spit out False
in this instance?
Furthermore, how does python's implementation differ from that of java or c++?
Typically, the floating point arithmetic is implemented directly by hardware. There are indeed special bit patterns for infinity and NaN, which are recognized by the hardware floating-point unit.
IEEE 64-bit floating-point numbers, the kind used in CPython on typical systems, have 1 bit for the sign, 11 bits for the exponent, and 52 bits for the mantissa. See https://en.wikipedia.org/wiki/Double-precision_floating-point_format
If the exponent contains 0b11111111111 (all ones), then the number is either inf or nan, depending on what is stored in the mantissa. Python does not need to do anything special to handle these cases. You will get the same results whether you compare the numbers in Python, C, Java, or assembly language.
Those are not python-specific behavior, it's rather the floating-point standard Python use (and possibly all common languages?).
nan
and inf
are special value of the IEEE_754 floating point standard.
They have internal representations (the bit sequence you mention) of course, but their behavior is not usual.
The behavior is not usual wrt other floats values, but it is well defined by IEEE_754. Implementation is handled at instruction level. (The processor handle this in its floating-point unit circuitry)
One specified and not trivial behavior, NaN != everything, including itself.
Knowing that, you can write something like:
def isNaN(f): return f != f