|
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