|
73 | 73 | \hsection{Floating Point Arithmetic}%
|
74 | 74 | \label{sec:floatarith}%
|
75 | 75 | %
|
76 |
| -\gitEvalPython{float_arith}{}{simple_datatypes/float_arith.py}% |
77 |
| -\listingBox{exec:float_arith}{Basic arithmetics with floating point numbers in \python.}{,style=python_console_style}% |
| 76 | +\gitEvalPython{float_arithmetics}{}{simple_datatypes/float_arithmetics.py}% |
| 77 | +\listingBox{exec:float_arithmetics}{Basic arithmetics with floating point numbers in \python.}{,style=python_console_style}% |
78 | 78 | %
|
79 | 79 | Floating point numbers in \python\ can be distinguished from \pythonils{int}\pythonIdx{int} by having a decimal dot in their text representation, i.e., \pythonil{5.0} is a \pythonilIdx{float} and \pythonil{5} is an \pythonilIdx{int}.
|
80 |
| -Let us now look at some examples for the basic arithmetic operations available for \pythonils{float}\pythonIdx{float} in \cref{exec:float_arith}. |
| 80 | +Let us now look at some examples for the basic arithmetic operations available for \pythonils{float}\pythonIdx{float} in \cref{exec:float_arithmetics}. |
81 | 81 |
|
82 | 82 | We already learned that the division operator~\pythonilIdx{/} always yields a \pythonilIdx{float} result.
|
83 | 83 | Therefore \pythonil{6 / 3} yields \pythonil{2.0} instead of \pythonil{2}.
|
|
162 | 162 | %
|
163 | 163 | \hsection{Back to Integers: Rounding}%
|
164 | 164 | %
|
165 |
| -\begin{figure}% |
166 |
| -\centering% |
167 |
| -\includegraphics[width=0.8\linewidth]{\currentDir/floatMathInConsoleRound}% |
168 |
| -\caption{Rounding \pythonilIdx{float} values to \pythonilIdx{int} values.}% |
169 |
| -\label{fig:floatMathInConsoleRound}% |
170 |
| -\end{figure}% |
| 165 | +\gitEvalPython{float_rounding}{}{simple_datatypes/float_rounding.py}% |
| 166 | +\listingBox{exec:float_rounding}{Rounding \pythonilIdx{float} values to \pythonilIdx{int} values.}{,style=python_console_style}% |
171 | 167 | %
|
172 | 168 | We already learned that a single \pythonilIdx{float} value inside a computation that otherwise uses \pythonils{int}\pythonIdx{int} basically forces the whole result to become a \pythonilIdx{float} as well.
|
173 | 169 | But maybe sometimes we want to have an \pythonilIdx{int} as result.
|
|
179 | 175 | If two integer numbers are equally close, it rounds it to the one that is even.
|
180 | 176 | This can be very surprising, as we learned in school that $x.5$ should be rounded to $x+1$.
|
181 | 177 | This will only happen with \pythonilIdx{round} if $x+1$~is even.
|
182 |
| -We find examples for the behavior of \pythonilIdx{round} in \cref{fig:floatMathInConsoleRound}. |
| 178 | +We find examples for the behavior of \pythonilIdx{round} in \cref{exec:float_rounding}. |
183 | 179 | \pythonil{round(0.4)} yields the integer~\pythonil{0}, as expected.
|
184 | 180 | \pythonil{round(0.5)} returns~\pythonil{0} as well, which one may not expect -- but \pythonil{0} is even and \pythonil{1} would be odd.
|
185 | 181 | \pythonil{round(0.6)} gives us the integer~\pythonil{1}.
|
|
233 | 229 | \label{fig:scientificNotation}%
|
234 | 230 | \end{figure}%
|
235 | 231 | %
|
236 |
| -\begin{figure}% |
237 |
| -\centering% |
238 |
| -% |
239 |
| -\includegraphics[width=0.8\linewidth]{\currentDir/floatMathInConsoleSciNot}% |
240 |
| -\caption{Examples for the scientific notation in \python.}% |
241 |
| -\label{fig:floatMathInConsoleSciNot}% |
242 |
| -\end{figure}% |
| 232 | +\gitEvalPython{float_scientific_notation}{}{simple_datatypes/float_scientific_notation.py}% |
| 233 | +\listingBox{exec:float_scientific_notation}{Examples of the scientific notation in \python.}{,style=python_console_style}% |
243 | 234 | %
|
244 | 235 | Earlier on, we wrote that \pythonils{float}\pythonIdx{float} can represent numbers as large as~$10^{300}$ or as small as~$10^{-300}$.
|
245 | 236 | This leads to the question how it would print such values on the console and how we can read them.
|
|
256 | 247 | This notation is illustrated in \cref{fig:scientificNotation}.
|
257 | 248 | \emph{This notation only applies to \pythonils{float}\pythonIdx{float}, \textbf{not} \pythonils{int}\pythonIdx{int}.}
|
258 | 249 |
|
259 |
| -In \cref{fig:floatMathInConsoleSciNot} we provide some examples for this notation. |
| 250 | +In \cref{exec:float_scientific_notation} we provide some examples for this notation. |
260 | 251 | When we write \pythonil{0.001} or \pythonil{0.0001} in a \python\ console, the output is still this same number.
|
261 | 252 | However, \pythonil{0.00009} is presented as \pythonil{9e-05}, which stands for~$9*10^{-5}$.%
|
262 | 253 | %
|
|
301 | 292 | \hsection{Limits and Special Floating Point Values: Infinity and \inQuotes{Not a Number}}%
|
302 | 293 | \label{sec:float:special}%
|
303 | 294 | %
|
304 |
| -\begin{figure}% |
305 |
| -\centering% |
306 |
| -\includegraphics[width=0.7\linewidth]{\currentDir/floatMathInConsoleZero}% |
307 |
| -\caption{What happens with very small floating point numbers in \python?\pythonIdx{0.0}}% |
308 |
| -\label{fig:floatMathInConsoleZero}% |
309 |
| -\end{figure}% |
| 295 | +% |
| 296 | +\gitEvalPython{float_very_small}{}{simple_datatypes/float_very_small.py}% |
| 297 | +\listingBox{exec:float_very_small}{What happens with very small floating point numbers in \python?\pythonIdx{0.0}.}{,style=python_console_style}% |
310 | 298 | %
|
311 | 299 | We already learned that the floating point type \pythonilIdx{float} can represent both very small and very large numbers.
|
312 | 300 | But we also know that it is internally stored as chunk of 64~bits.
|
|
321 | 309 | In its documentation~\cite{O2024JPSEJDKV2AS:CD}, we find that the minimum value is~$2^{-1074}$, which is approximately~$4.940\decSep656\decSep458\decSep412\decSep465\decSep44*10^{-324}$.
|
322 | 310 | So we would expect the smallest possible floating point value in \python\ to also be in this range.
|
323 | 311 |
|
324 |
| -In \cref{fig:floatMathInConsoleInf}, we take a look what happens if we approach this number. |
| 312 | +In \cref{exec:float_very_large}, we take a look what happens if we approach this number. |
325 | 313 | We use the scientific notation and begin to print the number~\pythonil{1e-323} (which is~$10^{-323}$).
|
326 | 314 | This number is correctly represented as \pythonilIdx{float} and shows up in the console exactly as we wrote it.
|
327 | 315 | However, if we go a bit smaller and enter \pythonil{9e-324}, which is~$9*10^{-324}=0.9*10^{-323}$, we find that it again shows up in the console as \pythonil{1e-323}.
|
|
343 | 331 | So we learned what happens if we try to define very small floating point numbers:
|
344 | 332 | They become zero.
|
345 | 333 |
|
346 |
| -\begin{figure}% |
347 |
| -\centering% |
348 |
| -\includegraphics[width=0.7\linewidth]{\currentDir/floatMathInConsoleInf}% |
349 |
| -\caption{What happens with very large floating point numbers in \python?\pythonIdx{inf}}% |
350 |
| -\label{fig:floatMathInConsoleInf}% |
351 |
| -\end{figure}% |
| 334 | +\gitEvalPython{float_very_large}{}{simple_datatypes/float_very_large.py}% |
| 335 | +\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} |
352 | 336 |
|
353 | 337 | But what happens to numbers that are too big for the available range?
|
354 | 338 | 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}$.
|
355 |
| -We can enter this value as \pythonilIdx{1.7976931348623157e+308}\pythonIdx{float!largest} and it indeed prints correctly in \cref{fig:floatMathInConsoleInf}. |
| 339 | +We can enter this value as \pythonilIdx{1.7976931348623157e+308}\pythonIdx{float!largest} and it indeed prints correctly in \cref{exec:float_very_large}. |
356 | 340 | 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}.
|
357 | 341 | However, if we try entering \pythonil{1.7976931348623159e+308} into the \python\ console, something strange happens:
|
358 | 342 | The output is \pythonilIdx{inf}.
|
|
391 | 375 | We can import it via \pythonil{from math import inf}\pythonIdx{inf}.
|
392 | 376 | 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}.
|
393 | 377 |
|
394 |
| -\begin{figure}% |
395 |
| -\centering% |
396 |
| -\includegraphics[width=0.8\linewidth]{\currentDir/floatMathInConsoleNaN}% |
397 |
| -\caption{Not a Number\pythonIdx{Not a Number}, i.e., \pythonilIdx{nan}.}% |
398 |
| -\label{fig:floatMathInConsoleNaN}% |
399 |
| -\end{figure}% |
400 |
| -list |
| 378 | +\gitEvalPython{float_nan}{}{simple_datatypes/float_nan.py}% |
| 379 | +\listingBox{exec:float_nan}{Not a Number\pythonIdx{Not a Number}, i.e., \pythonilIdx{nan}.}{,style=python_console_style}% |
| 380 | + |
401 | 381 | Now, \pythonilIdx{inf} not actually being~$\infty$ is a little bit weird.
|
402 |
| -But it can get even stranger, as you will see in \cref{fig:floatMathInConsoleNaN}. |
| 382 | +But it can get even stranger, as you will see in \cref{exec:float_nan}. |
403 | 383 | \pythonilIdx{inf} is a number which is too big to be represented as \pythonilIdx{float} \emph{or}~$\infty$.
|
404 | 384 | So it is natural to assume that \pythonil{inf - 1} remains \pythonilIdx{inf} and that even \pythonil{inf - 1e300} remains \pythonilIdx{inf} as well.
|
405 | 385 | However, what is \pythonil{inf - inf}?
|
|
421 | 401 | However, \pythonilIdx{nan} is \emph{really} different from really \emph{anything}.
|
422 | 402 | Therefore, \pythonil{nan == nan}\pythonIdx{==} is \pythonilIdx{False} and \pythonil{nan != nan}\pythonIdx{"!=} is \pythonilIdx{True}!
|
423 | 403 |
|
424 |
| -\begin{figure}% |
425 |
| -\centering% |
426 |
| -\includegraphics[width=0.8\linewidth]{\currentDir/floatMathInConsoleCheckFinite}% |
427 |
| -\caption{Checking for \pythonilIdx{nan} and \pythonilIdx{inf} via \pythonilIdx{isfinite}, \pythonilIdx{isinf}, and \pythonilIdx{isnan}.}% |
428 |
| -\label{fig:floatMathInConsoleCheckFinite}% |
429 |
| -\end{figure}% |
| 404 | +\gitEvalPython{float_check_finite}{}{simple_datatypes/float_check_finite.py}% |
| 405 | +\listingBox{exec:float_check_finite}{Checking for \pythonilIdx{nan} and \pythonilIdx{inf} via \pythonilIdx{isfinite}, \pythonilIdx{isinf}, and \pythonilIdx{isnan}.}{,style=python_console_style}% |
430 | 406 |
|
431 | 407 | Either way, the possible occurrence \pythonilIdx{inf} and \pythonilIdx{nan} in floating point computations is a cumbersome issue.
|
432 | 408 | If we want to further process results of a computation, we often want to make sure that it is neither \pythonilIdx{inf} nor \pythonilIdx{-inf} nor \pythonilIdx{nan}.
|
433 |
| -This can be done via the function \pythonilIdx{isfinite}, which we can import from the \pythonilIdx{math} module\pythonIdx{import}\pythonIdx{from}, as you can see in \cref{fig:floatMathInConsoleCheckFinite}. |
| 409 | +This can be done via the function \pythonilIdx{isfinite}, which we can import from the \pythonilIdx{math} module\pythonIdx{import}\pythonIdx{from}, as you can see in \cref{exec:float_check_finite}. |
434 | 410 | \pythonil{1e34} is a large number, but \pythonil{isfinite(1e34)} is certainly \pythonilIdx{True}.
|
435 | 411 | \pythonil{isfinite(inf)} and \pythonil{isfinite(nan)} are both \pythonilIdx{False}.
|
436 | 412 | The function \pythonilIdx{isinf}, again from the \pythonilIdx{math} module, checks if a \pythonilIdx{float} is infinite.
|
|
0 commit comments