Why does float('inf') == float('inf') return True, but float('inf') - float('inf') == float('inf') returns False?

Viewed 122

Why does this happen in Python?

  • float('inf') == float('inf') returns True,
  • float('inf') + float('inf') == float('inf') returns True,
  • float('inf') * float('inf') == float('inf') returns True,
  • float('inf') - float('inf') == float('inf') returns False,
  • float('inf') / float('inf') == float('inf') returns False.

My best guess, if I think about limits, is related with the result of this operation:

limx→+∞(f(x) ▢ g(x)) where limx→+∞ f(x) = +∞ and limx→+∞ g(x) = +∞, which returns +∞ if ▢ is + or *, but it is not defined (it could return every value) if ▢ is - or /.

I am very puzzled, though.

3 Answers

Before the comparison of

float('inf') - float('inf') == float('inf')

can be made, the result of

float('inf') - float('inf')

will be calculated. That result is NaN.

It is NaN because the amounts of infinity may differ. It's explained on the Stack Overflow sister site Math.SE, known as the Hilbert hotel paradox:

From a layman's perspective, imagine that I have an infinite number of hotel rooms, each numbered 1, 2, 3, 4, ...

Then I give you all of them. I would have none left, so ∞−∞=0

On the other hand, if I give you all of the odd-numbered ones, then I still have an infinite number left. So ∞−∞=∞.

Now suppose that I give you all of them except for the first seven. Then ∞−∞=7. While this doesn't explain why this is indeterminate, hopefully you can agree that it is indeterminate!

The best number to represent indeterminate is NaN. Comparing NaN to anything is always False, even comparing NaN against itself.

Besides that quite "logical" explanation, we find that Python uses IEEE754 representation for floating point calculation.

You'd typically need to buy the IEEE754 specification, but luckily we see some draft version online. The relevant chapter IMHO is 7.2:

For operations producing results in floating-point format, the default result of an operation that signals the invalid operation exception shall be a quiet NaN [...]

[...]

d) addition or subtraction or fusedMultiplyAdd: magnitude subtraction of infinities, such as: addition(+∞, −∞)

I don't think that's a problem with python.

infinity - infinity is undefined (mathematically), therefore it is not be equal to infinity.


>>> np.inf - np.inf
nan
>>> np.inf == np.inf
True

makes sense, we're comparing objects that are equal.

>>> (np.inf - np.inf) == np.inf
False

Also makes sense, we're comparing different objects.

All the answers python gave you, on the examples you posted, are right.

See answer by @thomas-weller but additionally, the issue boils down to this. Because there are multiple sizes of infinite we run into a problem when subtracting and dividing them.

Setting aside recent proof that some infinite sets thought to be of different size are in fact the the same size (Mathematicians Measure Infinities and Find They’re Equal).

The list of whole numbers is infinite and the list of real numbers is also infinite. However, the list of real numbers between any two adjacent whole numbers is also infinite.

float("inf") does not give a chance to say "this is infinite" vs "this is infinitely infinite" so we don't know which it is. Note I'm going to use two references from here on:

  • INF === infinite
  • INFINF === infinitely infinite

Now then where does that leave us:

float('inf') == float('inf') ==> True

It seems reasonable that: (INF or INFINF) is equal to (INF or INFINF)

float('inf') + float('inf') == float('inf')

It seems reasonable that: (INF or INFINF) + (INF or INFINF) is equal to (INF or INFINF)

float('inf') * float('inf') == float('inf')

It seems reasonable that: (INF or INFINF) * (INF or INFINF) is equal to (INF or INFINF)

float('inf') - float('inf') == float('inf')

Now we have a bit of a stickler. We conceptually have lots of potential answers. Given float('inf') - float('inf') then 0 is plausible as is -INFINF and INFINF. This result is undefined and as such nan. In fact, as @thomas-weller points out almost any answer might be plausible.

float('inf') / float('inf') == float('inf')

Same issue as above. This result is undefined given that we don't know how "big" any of the float("inf") are.

Related