|
363 | 363 | \listingBox{exec:float_very_large}{What happens with very large floating point numbers in \python?\pythonIdx{inf}.}{,style=python_console_style,literate={0}{0\-}1 {1}{1\-}1 {2}{2\-}1 {3}{3\-}1 {4}{4\-}1 {5}{5\-}1 {6}{6\-}1 {7}{7\-}1 {8}{8\-}1 {9}{9\-}1,breakatwhitespace=false,breaklines=true}
|
364 | 364 |
|
365 | 365 | But what happens to numbers that are too big for the available range?
|
366 |
| -Again, according to the nice documentation of \pgls{Java}, the maximum 64~bit double precision floating point number value is~$(2-2^{-52})*2^{1023}\approx1.797\decSep693\decSep134\decSep862\decSep315\decSep708\dots*10^{308}$. |
| 366 | +Again, according to the nice documentation of \pgls{Java}~\cite{O2024JPSEJDKV2AS:CD}, the maximum 64~bit double precision floating point number value is~$(2-2^{-52})*2^{1023}\approx1.797\decSep693\decSep134\decSep862\decSep315\decSep708\dots*10^{308}$. |
367 | 367 | We can enter this value as \pythonilIdx{1.7976931348623157e+308}\pythonIdx{float!largest} and it indeed prints correctly in \cref{exec:float_very_large}.
|
368 | 368 | If we step it up a little bit and enter \pythonil{1.7976931348623158e+308}, due to the limited precision, we again get \pythonilIdx{1.7976931348623157e+308}\pythonIdx{float!largest}.
|
369 | 369 | However, if we try entering \pythonil{1.7976931348623159e+308} into the \python\ console, something strange happens:
|
370 | 370 | The output is \pythonilIdx{inf}.
|
| 371 | +\pythonil{inf} means \emph{\inQuotes{too big to be represented as number with \pythonil{float},}} which obviously includes infinity~($+\infty$), but also simply all numbers bigger than~\pythonil{1.7976931348623158e+308}. |
| 372 | + |
371 | 373 | \pythonil{-1.7976931348623159e+308} gives us \pythonilIdx{-inf}.
|
372 | 374 | Multiplying this value by two, i.e., computing \pythonil{-1.7976931348623157e+308 * 2}, still yields \pythonil{-inf}.
|
373 | 375 | Intuitively, based on its name, one would assume that \pythonilIdx{inf} stands for \inQuotes{infinity} or~$\infty$.
|
|
399 | 401 | However, if we divide~1 by \pythonil{1.7976931348623159e+308}, we get~\pythonil{0.0}.
|
400 | 402 | The reason is that \pythonil{1.7976931348623159e+308} becomes \pythonilIdx{inf} and \pythonil{1 / inf}\pythonIdx{/} is~\pythonilIdx{0.0}.
|
401 | 403 |
|
402 |
| -Finally, \pythonilIdx{inf} also exists as constant in the \pythonilIdx{math} module. |
| 404 | +\pythonilIdx{inf} exists as constant in the \pythonilIdx{math} module. |
403 | 405 | We can import it via \pythonil{from math import inf}\pythonIdx{inf}.
|
404 | 406 | 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}.
|
405 | 407 |
|
|
409 | 411 | Now, \pythonilIdx{inf} not actually being~$\infty$ is a little bit weird.
|
410 | 412 | But it can get even stranger, as you will see in \cref{exec:float_nan}.
|
411 | 413 | \pythonilIdx{inf} is a number which is too big to be represented as \pythonilIdx{float} \emph{or}~$\infty$.
|
| 414 | +Once a variable has the value \pythonilIdx{inf}, however, it is treated as if it was actually infinity. |
412 | 415 | So it is natural to assume that \pythonil{inf - 1} remains \pythonilIdx{inf} and that even \pythonil{inf - 1e300} remains \pythonilIdx{inf} as well.
|
413 | 416 | However, what is \pythonil{inf - inf}?
|
414 |
| -Mathematically speaking, this is very dodgy and $\infty-\infty$ as such is not a thing. |
| 417 | +Mathematically speaking, this is very dodgy and $\infty-\infty$ as such is not a~\inQuotes{thing}. |
415 | 418 | Or \emph{not a number}\pythonIdx{Not a Number}.
|
416 | 419 | Or \pythonilIdx{nan}, which stands for, well, Not a Number\pythonIdx{Not a Number}.
|
417 | 420 |
|
418 | 421 | \pythonilIdx{nan} means that the result of a computation is neither a finite number or infinite.
|
419 |
| -It is the result of shenanigans such as \pythonil{inf - inf} or \pythonil{inf / inf}. |
| 422 | +It is the result of shenanigans such as \pythonil{inf - inf} or \pythonil{inf / inf} or \pythonil{0 * inf}. |
420 | 423 | A \pythonilIdx{nan} value anywhere in a computation infects the result of the computation to also become \pythonilIdx{nan}.
|
421 | 424 | \pythonil{nan + 1} remains \pythonilIdx{nan} and so does \pythonil{nan + inf}.
|
422 | 425 |
|
|
429 | 432 | However, \pythonilIdx{nan} is \emph{really} different from really \emph{anything}.
|
430 | 433 | Therefore, \pythonil{nan == nan}\pythonIdx{==} is \pythonilIdx{False} and \pythonil{nan != nan}\pythonIdx{"!=} is \pythonilIdx{True}!
|
431 | 434 |
|
| 435 | +Interestingly, we said that \pythonil{inf} behaves more or less like~$\infty$ in computations. |
| 436 | +Except that \pythonil{inf == inf} is \pythonil{True}, which is strange, because \pythonil{inf - inf} is undefined. |
| 437 | +But OK, let's just accept that somethings are a bit strange and move on. |
| 438 | + |
432 | 439 | \gitEvalPython{float_check_finite}{}{simple_datatypes/float_check_finite.py}%
|
433 | 440 | \listingBox{exec:float_check_finite}{Checking for \pythonilIdx{nan} and \pythonilIdx{inf} via \pythonilIdx{isfinite}, \pythonilIdx{isinf}, and \pythonilIdx{isnan}.}{,style=python_console_style}%
|
434 | 441 |
|
|
0 commit comments