|
31 | 31 | This datatype represents numbers usually in the same format as \pythonil{double}s in the \pgls{C}~programming language~\cite{PSF2024NTIFC}, which, in turn, internally have a 64~bit IEEE~Standard 754 floating point number layout~\cite{IEEE2019ISFFPA,H1997IS7FPN}.
|
32 | 32 | The idea behind this standard is to represent both very large numbers, like~$10^{300}$ and very small numbers, like~$10^{-300}$.
|
33 | 33 | In order to achieve this, the 64~bits are divided into three pieces, as illustrated in \cref{fig:floatIEEEStructure}.
|
34 |
| - |
| 34 | +% |
| 35 | +\noviceHint{% |
| 36 | +You just need to understand that \pythonil{float}s have limited precision. % |
| 37 | +You can jump right to the next section.}% |
| 38 | +% |
35 | 39 | The first part, the so-called \pgls{significand} or \pgls{mantissa}, consists of 52~bits, represents the digits of the number.
|
36 | 40 | 52~bits can represent $52\log_2 10\approx 15$~decimal digits, meaning that we can represent numbers to a precision of about 15~digits.
|
37 | 41 | If we would just use 52~bits, then this would limit us to represent numbers maybe from~$0$ to~$2^{52}-1$ at a resolution of~$1$.
|
|
131 | 135 | Calculating \pythonil{asin(sin(0.925))} indeed yields~\pythonil{0.9250000000000002}.
|
132 | 136 | Due to the periodicity of the trigonometric functions, $\arccos{\cos{-0.3}}$ is~$0.3$ and \pythonil{acos(cos(-0.3))} results in~\pythonil{0.30000000000000016}.
|
133 | 137 | For $\arctan{\tan{1}}$ we even get the exact result \pythonil{1.0} by computing \pythonil{atan(tan(1))}.%
|
| 138 | +\endhsection% |
| 139 | +% |
| 140 | +\hsection{The Scientific Notation}% |
| 141 | +% |
| 142 | +\begin{figure}% |
| 143 | +\centering% |
| 144 | +\begin{tabular}{r@{}r@{{\color{orange}\textbf{e}}}l@{~~$\equiv$~~}r@{}l}% |
| 145 | +\multicolumn{2}{c}{$\beta$}&$\gamma$&\multicolumn{2}{c}{$\alpha$}\\\hline% |
| 146 | +&\texttt{A.BCDEFG}{\dots}&\texttt{\color{red}{+}}\texttt{HIJ}&&$\texttt{A.BCDEFG}{\dots}*10^{HIJ}$\\ |
| 147 | +&\texttt{A.BCDEFG}{\dots}&\texttt{\color{red}{-}}\texttt{HIJ}&&$\texttt{A.BCDEFG}{\dots}*10^{{\color{red}{-}}HIJ}$\\ |
| 148 | +{\color{blue}{-}}&\texttt{A.BCDEFG}{\dots}&\texttt{\color{red}{+}}\texttt{HIJ}&${\color{blue}{-}}$&$\texttt{A.BCDEFG}{\dots}*10^{HIJ}$\\ |
| 149 | +{\color{blue}{-}}&\texttt{A.BCDEFG}{\dots}&\texttt{\color{red}{-}}\texttt{HIJ}&${\color{blue}{-}}$&$\texttt{A.BCDEFG}{\dots}*10^{{\color{red}{-}}HIJ}$% |
| 150 | +\end{tabular}% |
| 151 | +% |
| 152 | +\caption{The structure of the scientific notation for floating point numbers in \python, which represent a value~$\alpha$ in the form~$\beta*10^{\gamma}$.}% |
| 153 | +\label{fig:scientificNotation}% |
| 154 | +\end{figure}% |
| 155 | +% |
| 156 | +\begin{figure}% |
| 157 | +\centering% |
| 158 | +% |
| 159 | +\includegraphics[width=0.8\linewidth]{\currentDir/floatMathInConsoleSciNot}% |
| 160 | +\caption{Examples for the scientific notation in \python.}% |
| 161 | +\label{fig:floatMathInConsoleSciNot}% |
| 162 | +\end{figure}% |
| 163 | +% |
| 164 | +Earlier on, we wrote that \pythonil{float}s can represent numbers as large as~$10^{300}$ or as small as~$10^{-300}$. |
| 165 | +This leads to the question how it would print such values on the console and how we can read them. |
| 166 | +While it would be hugely impractical to write a~1 followed by 300~zeros to represent~$10^{300}$, it would also be \emph{wrong}. |
| 167 | +We also already know the reason for this: |
| 168 | +A \pythonil{float} is accurate to 15~decimals. |
| 169 | +So basically, the first 15~zeros would be correct, but the values of the other digits are actually \emph{undefined}. |
| 170 | + |
| 171 | +\python, like many programming languages, solves this problem by using the \emph{scientific notation} for floating point numbers. |
| 172 | +It uses this notation for any (absolute) \pythonil{float} value smaller than~$10^{-4}$ or larger than or equal to~$10^{16}$. |
| 173 | +Such numbers~$\alpha$ are then represented in the form~$\beta*10^{\gamma}$ (such that $\beta*10^{\gamma}=\alpha$, obviously). |
| 174 | +Since we cannot write this so nicely in a console, a lowercase~\texttt{e} takes the place of the~$10$ and $\beta$ and $\gamma$ are written as normal text. |
| 175 | +In order to make sure that each number~$\alpha$ has unique representation, it is defined that $\alpha$ must have exactly one non-zero leading digit, which may be followed by a decimal dot and then a fractional part. |
| 176 | +This notation is illustrated in \cref{fig:scientificNotation}. |
| 177 | +\emph{This notation only applies to \pythonil{float}s, \textbf{not} \pythonil{int}s.} |
| 178 | + |
| 179 | +In \cref{fig:floatMathInConsoleSciNot} we provide some examples for this notation. |
| 180 | +When we write \pythonil{0.001} or \pythonil{0.0001} in a \python\ console, the output is still this same number. |
| 181 | +However, \pythonil{0.00009} is presented as \pythonil{9e-05}, which stands for~$9*10^{-5}$.% |
134 | 182 | %
|
| 183 | +\begin{sloppypar}% |
| 184 | +Did you know that you are allowed to insert underscores (\pythonil{_}) anywhere in a number as a visual aid? |
| 185 | +If not, you know now. |
| 186 | +We can write $10^{15}$ as \pythonil{float} by typing \pythonil{1_000_000_000_000_000.0}. |
| 187 | +This equals the much less readable \pythonil{1000000000000000.0}. |
| 188 | +We can do the same for $9*10^{15}$ by writing \pythonil{9_000_000_000_000_000.0} and get \pythonil{9000000000000000.0}. |
| 189 | +However, if we write \pythonil{9_999_999_999_999_999.0}, something interesting happens: |
| 190 | +We get \pythonil{1e+16}, i.e., $10^{16}$. |
| 191 | +This is because of the limited precision of the floating point numbers, namely the 15~digits often mentioned above. |
| 192 | +We cannot distinguish $10^{16}$ and $10^{16}-1$ when using \python's \pythonil{float}s. |
| 193 | +Indeed, writing \pythonil{10_000_000_000_000_000.0} also yields \pythonil{1e+16}.% |
| 194 | +\end{sloppypar}% |
| 195 | +% |
| 196 | +This notation can also show really big numbers. |
| 197 | +For example $10^{200}$, i.e., \pythonil{10.0 ** 200}, shows up as \pythonil{1e+200}. |
| 198 | +The really really small number $-10^{-200}$ in turn, computed via \pythonil{-(10.0 ** -200)}, is denoted as \pythonil{-1e-200}. |
| 199 | + |
| 200 | +The numbers are always scaled such that they begin with non-zero digit followed by the fractional part separated with a decimal dot, if need be. |
| 201 | +Examples for this are \pythonil{2.1 ** -300.1} which yields \pythonil{2.0044242594658263e-97} and \pythonil{10.0 ** 200.1}, which turns up as \pythonil{1.2589254117941507e+200}. |
| 202 | + |
| 203 | +Of course, you can also input numbers in scientific notation. |
| 204 | +If you write \pythonil{2e5}, this turns into \pythonil{200000.0}. |
| 205 | +Of course, the number is stored as a \pythonil{float} internally and this \pythonil{float} does not know from which kind of text it was created. |
| 206 | +When it is turned back into text, it becomes a \inQuotes{normal number,} because it is less than~$10^{16}$. |
| 207 | +And so does \pythonil{2.34e10}, which becomes \pythonil{23400000000.0}. |
| 208 | +\pythonil{2.3456e16} however indeed remains \pythonil{2.3456e16}. |
| 209 | + |
| 210 | +You can even violate the scientific notation a bit when entering numbers if you feel naughty. |
| 211 | +\pythonil{-12e30}, for example, would better be written as \pythonil{-1.2e+31}, which the \python\ console will do for you in its output. |
| 212 | +Similarly, \pythonil{0.023e-20} becomes \pythonil{2.3e-22}. |
135 | 213 | \endhsection%
|
136 | 214 | %
|
137 | 215 | \endhsection%
|
|
0 commit comments