12

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++?

cs95
  • 379,657
  • 97
  • 704
  • 746
  • 1
    Because the floating point machine instructions for comparison return false for comparing a nan to anything, including itself – camelccc Jul 01 '17 at 20:02
  • 10
    This has to do with the [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) standard. – E_net4 Jul 01 '17 at 20:04
  • 1
    Almost all programming languages use IEEE 754 for floating point values, which precisely defines what those special values are, how they are represented and how they behave in various operations. – Matteo Italia Jul 01 '17 at 20:04
  • Modern cpu:s have support for that. It does not need to be 'implemented' – klutt Jul 01 '17 at 20:04
  • 2
    Please read quite classic paper wrt FP math: http://www.lsi.upc.edu/~robert/teaching/master/material/p5-goldberg.pdf – Severin Pappadeux Jul 01 '17 at 20:06
  • Fantastic. I had no idea that CPUs natively supported infinity and nan. I always thought they were application level concepts. – cs95 Jul 01 '17 at 20:07

2 Answers2

10

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.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • I think it would be useful to mention the hardware instruction(s) for comparing floating-point numbers is designed to indicate that two operands are not equal if either one of them is a NaN, even if they have identical bit patterns. The author’s question suggests they may believe identical bit patterns necessarily indicate equality, or at least they do not understand how identical bit patterns could be said to be not equal. – Eric Postpischil Jul 01 '17 at 21:53
  • Thanks for answering. This makes sense to me. – cs95 Jul 01 '17 at 22:24
  • @EricPostpischil: That doesn't sound useful at all to mention, it would just be duplicating the information in your comment. Next time, if you have information useful to the person who asked the question, either suggest an edit or post a comment directed at the question asker. – Dietrich Epp Jul 01 '17 at 22:30
5

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
Håken Lid
  • 22,318
  • 9
  • 52
  • 67
johan d
  • 2,798
  • 18
  • 26