|
269 | 269 | \begin{figure}%
|
270 | 270 | \centering%
|
271 | 271 | \includegraphics[width=0.7\linewidth]{\currentDir/floatMathInConsoleZero}%
|
272 |
| -\caption{What happens with very small floating point numbers in \python?}% |
| 272 | +\caption{What happens with very small floating point numbers in \python?\pythonIdx{0.0}}% |
273 | 273 | \label{fig:floatMathInConsoleZero}%
|
274 | 274 | \end{figure}%
|
275 | 275 | %
|
|
299 | 299 | Matter of fact, \pythonil{6e-324}, \pythonil{5e-324}, \pythonil{4e-324}, and \pythonil{3e-324} all map to this same \pythonil{float}.
|
300 | 300 |
|
301 | 301 | It turns out that this number is already the smallest \pythonil{float} that can be represented:
|
302 |
| -\pythonil{2e-324} simply becomes \pythonil{0.0}. |
| 302 | +\pythonil{2e-324} simply becomes \pythonilIdx{0.0}. |
303 | 303 | This value is simply too small to be represented as a 64~bit / double precision IEEE~Standard 754 floating point number~\cite{IEEE2019ISFFPA,H1997IS7FPN}.
|
304 | 304 | The text \pythonil{2e-324} that we enter into the \python\ console will therefore be translated to the \pythonil{float}~\pythonil{0.0}.
|
305 | 305 | The comparison \pythonil{2e-324 == 0.0}\pythonIdx{==} therefore results in \pythonilIdx{True}, while \pythonil{3e-324 == 0.0} is still \pythonilIdx{False}.
|
|
309 | 309 | \begin{figure}%
|
310 | 310 | \centering%
|
311 | 311 | \includegraphics[width=0.7\linewidth]{\currentDir/floatMathInConsoleInf}%
|
312 |
| -\caption{What happens with very large floating point numbers in \python?}% |
| 312 | +\caption{What happens with very large floating point numbers in \python?\pythonIdx{inf}}% |
313 | 313 | \label{fig:floatMathInConsoleInf}%
|
314 | 314 | \end{figure}%
|
315 | 315 |
|
|
321 | 321 | The output is \pythonilIdx{inf}.
|
322 | 322 | \pythonil{-1.7976931348623159e+308} gives us \pythonilIdx{-inf}.
|
323 | 323 | Multiplying this value by two, i.e., computing \pythonil{-1.7976931348623157e+308 * 2}, still yields \pythonil{-inf}.
|
324 |
| -\pythonil{inf} stands for \inQuotes{infinity} or~$\infty$. |
325 |
| -However, it \emph{actually} means \emph{too big to represent as \pythonil{float}}. |
| 324 | +Intuitively, based on its name, one would assume that \pythonil{inf} stands for \inQuotes{infinity} or~$\infty$. |
| 325 | +However, it \emph{actually} means \emph{too big to represent as \pythonil{float} or~$\infty$}. |
326 | 326 | If we enter numbers that are too big or exceed the valid range of \pythonil{float} by multiplication, addition, subtraction, or division, we simply get~\pythonil{inf}.
|
327 | 327 | This does not actually mean \inQuotes{mathematical infinity,} because, while \pythonil{-1.7976931348623159e+308} is very big, it is not infinitely big.
|
328 | 328 | It simply means that the number is too big to put it into a 64~bit \pythonil{float}.
|
|
350 | 350 | However, if we divide~1 by \pythonil{1.7976931348623159e+308}, we get~\pythonil{0.0}.
|
351 | 351 | The reason is that \pythonil{1.7976931348623159e+308} becomes \pythonil{inf} and \pythonil{1 / inf} is~\pythonil{0}.
|
352 | 352 |
|
353 |
| -Finally, \pythonil{inf} also exists as constant in the \pythonil{math} module. |
| 353 | +Finally, \pythonilIdx{inf} also exists as constant in the \pythonil{math} module. |
354 | 354 | We can import it via \pythonil{from math import inf}\pythonIdx{inf}.
|
355 |
| -And indeed, since the text \pythonil{1.7976931348623159e+308} is parsed to a \pythonil{float} value of \pythonil{inf}, we find that \pythonil{1.7976931348623159e+308 == inf} yields~\pythonilIdx{True}.% |
| 355 | +And indeed, since the text \pythonil{1.7976931348623159e+308} is parsed to a \pythonilIdx{float} value of \pythonilIdx{inf}, we find that \pythonil{1.7976931348623159e+308 == inf} yields~\pythonilIdx{True}. |
| 356 | + |
| 357 | +\begin{figure}% |
| 358 | +\centering% |
| 359 | +\includegraphics[width=0.8\linewidth]{\currentDir/floatMathInConsoleNaN}% |
| 360 | +\caption{Not-a-Number, i.e., \pythonilIdx{nan}.}% |
| 361 | +\label{fig:floatMathInConsoleNaN}% |
| 362 | +\end{figure}% |
| 363 | + |
| 364 | +Now, \pythonilIdx{inf} not actually being~$\infty$ is a little bit weird. |
| 365 | +But it can get even stranger, as you will see in \cref{fig:floatMathInConsoleNaN}. |
| 366 | +\pythonilIdx{inf} is a number which is too big to be represented as \pythonilIdx{float} \emph{or}~$\infty$. |
| 367 | +So it is natural to assume that \pythonil{inf - 1} remains \pythonilIdx{inf} and that even \pythonil{inf - 1e300} remains \pythonilIdx{inf} as well. |
| 368 | +However, what is \pythonil{inf - inf}? |
| 369 | +Mathematically speaking, this is very dodgy and $\infty-\infty$ as such is not a thing. |
| 370 | +Or \emph{not a number}\pythonIdx{Not a Number}. |
| 371 | +Or \pythonilIdx{nan}, which stands for, well, Not a Number\pythonIdx{Not a Number}. |
| 372 | + |
| 373 | +\pythonilIdx{nan} means that the result of a computation is neither a finite number or infinite. |
| 374 | +It is the result of shenanigans such as \pythonil{inf - inf} or \pythonil{inf / inf}. |
| 375 | +A \pythonilIdx{nan} value anywhere in a computation infects the result of the computation to also become \pythonilIdx{nan}. |
| 376 | +\pythonil{nan + 1} remains \pythonil{nan} and so does \pythonil{nan + inf}. |
| 377 | + |
| 378 | +The value \pythonil{nan} is different from \emph{any} value. |
| 379 | +\pythonil{nan == 1} is \pythonilIdx{False} and \pythonil{nan != 1} is \pythonilIdx{True} (\pythonilIdx{!=} checks for inequality). |
| 380 | +While all other float values are equal to themselves and -- therefore -- not different from themselves. |
| 381 | +Thus \pythonil{1 != 1} is obviously \pythonilIdx{False}, \pythonil{inf == inf} is \pythonilIdx{True} and \pythonil{inf != inf} is \pythonilIdx{False}. |
| 382 | +However, \pythonilIdx{nan} is \emph{really} different from really \emph{anything}. |
| 383 | +Therefore, \pythonil{nan == nan} is \pythonilIdx{False} and \pythonil{nan != nan} is \pythonilIdx{True}! |
356 | 384 | %
|
357 | 385 | \endhsection%
|
358 | 386 | %
|
|
0 commit comments