Today I learned about the math.nextafter method.

Code snippet showing the `nextafter` method.

math.nextafter

0 is a neat number, isn't it?

Perhaps one of the greatest discoveries of mankind.

But what's the number that comes after 0? That would be the smallest number in the set \(]0, +\inf[\), if you're familiar with the mathematical notation for sets.

In short, \([a, b]\) is the contiguous set of numbers \(x\) that satisfy the restriction \(a \leq x \leq b\). Notice how \(a\) and \(b\) are included inside \([a, b]\) because the brackets are closed. If the brackets are open, then that number is not included.

For the intervals below, \(x\) belongs to it if...

  • \([a, b]\) β†’ \(a \leq x \leq b\);
  • \([a, b[\) β†’ \(a \leq x < b\);
  • \(]a, b]\) β†’ \(a < x \leq b\); and
  • \(]a, b[\) β†’ \(a < x < b\).

So, in \(]0, +\infty[\), nor 0, nor \(+\infty\) are included. Thus, what's the minimum element of this interval? Well, there isn't any!

Mathematically speaking, there is no minimum in the interval \(]0, +\infty[\). Why not? Whatever you pick as a potential minimum \(m\), \(m/2\) will be smaller than \(m\) and still be greater than \(0\), that is, \(0 < m/2 < m < +\infty\), and so \(m/2\) is in \(]0, +\infty[\).

That's interesting, right?

But this is a whole other story if we go into the programming real! Because of how floats are represented, Python has a number that comes immediately after 0. So, what is it?

Here it is:

>>> import math
>>> math.nextafter(0, 1)
5e-324

That's \(5 \times 10^{-324}\), it's freakishly small!

(Your result may differ from mine, although I'm not sure if it will. Leave a comment below if it does!)

So, what's the role of the math.nextafter method?

>>> help(math.nextafter)
Help on built-in function nextafter in module math:

nextafter(x, y, /)
    Return the next floating-point value after x towards y.

Hence, nextafter looks at x and then checks what's the float that's immediately next to x, if you walk in the direction of y. If I set x to zero and y to one, I get the smallest float that Python can represent on my machine.

So, what's the next float that Python can represent after 1?

Give it some thought.

Here it is:

>>> math.nextafter(1, 999)
1.0000000000000002

I'll be honest, for a second I thought it should've been 1 + 5e-324, but it makes sense it wasn't that. Floating point numbers have limited precision, right? And one thing that's limited is the size of the mantissa: the stuff that comes after the decimal point.

Above, we can see that the mantissa has 16 digits, and that's the size of the mantissa in Python.

So, what's the next number after 10?

Give it some thought.

Here it is:

>>> math.nextafter(10, 999)
10.000000000000002

If you count, now there's only 15 digits to the right of the decimal point... But I thought the size of the mantissa was 16 digits..?

And it is!

The mantissa is the size of the decimal part when the number is written in scientific notation!

Using string formatting, we can see that the value above has indeed 16 digits in its mantissa:

>>> f"{math.nextafter(10, 999):.16E}"
'1.0000000000000002E+01'        # ← 10.000000000000002 in scientific notation.

If you are not sure what just happened, don't worry. I'll soon write a Pydon't about string formatting!

That's it for now! Stay tuned and I'll see you around!

By the way, here's the tweet I learned this from:

Become a better Python 🐍 developer πŸš€

+35 chapters. +400 pages. Hundreds of examples. Over 30,000 readers!

My book β€œPydon'ts” teaches you how to write elegant, expressive, and Pythonic code, to help you become a better developer. >>> Download it here πŸπŸš€.

Previous Post Next Post

Blog Comments powered by Disqus.