<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Siphiwe</title>
    <description>The latest articles on DEV Community by Siphiwe (@theabstract).</description>
    <link>https://dev.to/theabstract</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F911159%2F30481523-7d06-4c0c-af47-df73de08f1c5.png</url>
      <title>DEV Community: Siphiwe</title>
      <link>https://dev.to/theabstract</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/theabstract"/>
    <language>en</language>
    <item>
      <title>Understanding Why Floats Are Not Real Numbers</title>
      <dc:creator>Siphiwe</dc:creator>
      <pubDate>Thu, 22 Sep 2022 20:04:52 +0000</pubDate>
      <link>https://dev.to/theabstract/understanding-why-floats-are-not-real-numbers-2ih0</link>
      <guid>https://dev.to/theabstract/understanding-why-floats-are-not-real-numbers-2ih0</guid>
      <description>&lt;h2&gt;
  
  
  floats ≠ ℝ
&lt;/h2&gt;

&lt;p&gt;Computers represent numbers in binary digits, the language of zeros and ones. Let's explore  how this is done, and why floats can only be considered as approximately real numbers.&lt;br&gt;
Our normal number system is represented in &lt;strong&gt;base ten&lt;/strong&gt;, with the usual digits, which we can expand like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;437 = 400    + 30     + 7
    = 4(100) + 3(10)  + 7(1)
    = 4(10²) + 3(10¹) + 7(10⁰)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Binary numbers are represented in &lt;strong&gt;base two&lt;/strong&gt; like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 = 0
1 = 1
2 = 1 0
3 = 1 1
4 = 1 0 0
5 = 1 0 1
6 = 1 1 0
7 = 1 1 1
8 = 1 0 0 0
9 = 1 0 0 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Given a number x in decimal form, we can find its binary form by hand. We simply subtract from x the largest powers of two smaller x. By keeping track of what powers we used and did not, we will have the binary form.&lt;br&gt;
For example, this is how we find the binary form of 237:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;237 - 128 = 109
109 - 64  = 45
45  - 32  = 13
13  - 8   = 5
5   - 4   = 1
1   - 1   = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and these are the powers of two that were used&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;256 128 64 32 16 8 4 2 1
      1  1  1  0 1 1 0 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The binary form of 237 is 11101101. Notice that 256 is excluded since we didn't use it, as a convention we are ignoring leading zeros that occur to the left of the first instance of 1 in the number.&lt;/p&gt;
&lt;h2&gt;
  
  
  A integer to binary function
&lt;/h2&gt;

&lt;p&gt;Suppose we have to convert 19 to its binary representation. From what  we've covered we know it should be:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x = 19 = 1(2⁴) + 0(2³) + 0(2²) + 1(2¹) + 1(2⁰) = 10011.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is what our function needs to do:&lt;br&gt;
Take the remainder of x relative to 2 (x % 2), this gives us the last binary bit.&lt;br&gt;
Then integer division by 2, which shifts all the bits to the right: &lt;br&gt;
x//2 = 1(2³) + 0(2²) + 0(2¹) + 1(2⁰) = 1001.&lt;/p&gt;

&lt;p&gt;Repeating this process will give us the rest of the bits.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;As expected, running &lt;code&gt;to_binary&lt;/code&gt; with x = 19 matches the result we got by hand 😎.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ python to_binary.py
The binary representation of 19 is 10011.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  What about fractions?
&lt;/h2&gt;

&lt;p&gt;Running &lt;code&gt;to_binary&lt;/code&gt; with x = 3/8 results in:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ python to_binary.py
The binary representation of 0.375 is 0.375.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Clearly this is wrong, 0.375 is what we want the binary representation of 🤦🏾! So we need a function that can handle fractions; lets stick to fractions that are at most 1 to keep things simple (&lt;em&gt;see the resources at the end for a deeper dive into floating-point arithmetic&lt;/em&gt;).&lt;br&gt;
For 𝑥 = 3/8 we know that; 3/8 = 0.375 = 3/10 + 7/10² + 5/10³. To get the binary form the procedure is this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Multiply 𝑥 by a power of 2 large enough to convert it into a whole number.&lt;/li&gt;
&lt;li&gt;Convert this whole number into binary.&lt;/li&gt;
&lt;li&gt;Divide the result by the power of 2 used in step 1. The integer part of this step tells you by how much to shift the decimal point.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For our example…&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;0.375(2³)=3&lt;/li&gt;
&lt;li&gt;3 in binary is 11&lt;/li&gt;
&lt;li&gt;Dividing by 2³ gives 1.375 so we shift one place from 0.11 to get 0.011, which is 0.375 in binary form&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If there is no integer 𝑝 such that 𝑥(2ᵖ) is a whole number, then the internal representation will always be an approximation. This is why testing for the equality (&lt;code&gt;==&lt;/code&gt;) of floats is not exact, and will lead to very bizarre behaviour.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; x = 0.1 + 0.2
&amp;gt;&amp;gt;&amp;gt; if x == 0.3: print('Duh!🙄')
... else: print('WTF...🧐?')
...
WTF...🧐?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  the decimal to binary function…
&lt;/h2&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;decimal_to_binary&lt;/code&gt; with x = 3/8 now results in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ python decimal_to_binary.py
The binary representation of 0.375 is 0.011.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exactly what we expected 😎.&lt;/p&gt;




&lt;p&gt;Learn more&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Floating-point_arithmetic"&gt;Floating-point arithmetic (wikipedia)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://diybigdata.net/2016/07/data-science-and-floating-point-arithmetic/"&gt;What Every Data Scientist Should Know About Floating-Point Arithmetic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The classic &lt;a href="https://people.cs.pitt.edu/~cho/cs1541/current/handouts/goldberg.pdf"&gt;What Every Computer Scientist Should Know About Floating-Point Arithmetic&lt;/a&gt;, by David Goldberg (deep dive, not for the math-phobic)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>python</category>
      <category>computerscience</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
