<?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: Craftstack Academy</title>
    <description>The latest articles on DEV Community by Craftstack Academy (@cstackacademy).</description>
    <link>https://dev.to/cstackacademy</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4228756%2F9b623996-b69a-4f52-84a7-20dcb26a0469.jpg</url>
      <title>DEV Community: Craftstack Academy</title>
      <link>https://dev.to/cstackacademy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cstackacademy"/>
    <language>en</language>
    <item>
      <title>Why Does 0.1 + 0.2 Not Equal 0.3 in Python?</title>
      <dc:creator>Craftstack Academy</dc:creator>
      <pubDate>Thu, 05 Nov 2026 14:37:31 +0000</pubDate>
      <link>https://dev.to/cstackacademy/why-does-01-02-not-equal-03-in-python-14k</link>
      <guid>https://dev.to/cstackacademy/why-does-01-02-not-equal-03-in-python-14k</guid>
      <description>&lt;p&gt;Open Python and type this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'd expect &lt;code&gt;0.3&lt;/code&gt;. Python gives you 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.30000000000000004
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it gets stranger:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're learning to code, this is the moment you start wondering whether you broke something. You didn't. Python is doing exactly what it was designed to do, and so are JavaScript, Java, C# and almost every other language. Try &lt;code&gt;0.1 + 0.2&lt;/code&gt; in your browser's console and you'll get the same &lt;code&gt;0.30000000000000004&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's look at why, and what to do about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Computers store numbers in binary
&lt;/h2&gt;

&lt;p&gt;You count in base 10: every digit is a number of ones, tens, hundreds, and after the decimal point, tenths, hundredths and so on.&lt;/p&gt;

&lt;p&gt;Computers count in base 2 (binary). After the "binary point" they only have halves, quarters, eighths, sixteenths…&lt;/p&gt;

&lt;p&gt;Some numbers fit perfectly into that system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;0.5&lt;/code&gt; is one half → exact&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0.25&lt;/code&gt; is one quarter → exact&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0.75&lt;/code&gt; is a half plus a quarter → exact&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But &lt;code&gt;0.1&lt;/code&gt; (one tenth) can't be built from halves, quarters and eighths. In binary it's an endless repeating pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.0001100110011001100110011...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The same problem you already know: 1/3
&lt;/h2&gt;

&lt;p&gt;You've seen this in base 10. Try writing one third as a decimal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.3333333333...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The threes never stop. At some point you have to cut it off, and the number you wrote down is &lt;em&gt;almost&lt;/em&gt; one third, but not exactly.&lt;/p&gt;

&lt;p&gt;The computer has the same problem with &lt;code&gt;0.1&lt;/code&gt;, just in binary. It has a fixed amount of space for each number (64 bits), so it stores the closest value it can fit. You can see the number Python actually stored:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;decimal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.1000000000000000055511151231257827021181583404541015625
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So &lt;code&gt;0.1&lt;/code&gt; is really a tiny bit more than 0.1. The same goes for &lt;code&gt;0.2&lt;/code&gt;. Add two slightly-off numbers and the tiny errors add up. That's where the extra &lt;code&gt;...04&lt;/code&gt; comes from.&lt;/p&gt;

&lt;p&gt;It's not only &lt;code&gt;0.1 + 0.2&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.7999999999999999
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why &lt;code&gt;print(0.1)&lt;/code&gt; still shows 0.1
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;0.1&lt;/code&gt; is stored as &lt;code&gt;0.1000000000000000055...&lt;/code&gt;, why does &lt;code&gt;print(0.1)&lt;/code&gt; show &lt;code&gt;0.1&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Python is being helpful. When it prints a float, it shows the &lt;em&gt;shortest&lt;/em&gt; number that maps back to the same stored value. For &lt;code&gt;0.1&lt;/code&gt;, that's simply &lt;code&gt;0.1&lt;/code&gt;. But after the addition, the result lands on a slightly different stored value, and the shortest way to write that one is &lt;code&gt;0.30000000000000004&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to fix it
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Round when you display a result
&lt;/h3&gt;

&lt;p&gt;If you only need to &lt;em&gt;show&lt;/em&gt; the number, round it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.3
0.30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Never compare floats with &lt;code&gt;==&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is the real lesson. Instead of asking "are these exactly equal?", ask "are these close enough?":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;math.isclose()&lt;/code&gt; lets a tiny difference through, which is exactly what you want when working with decimals.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Use &lt;code&gt;Decimal&lt;/code&gt; when every cent matters
&lt;/h3&gt;

&lt;p&gt;For money and other places where you need exact decimal math, use the &lt;code&gt;decimal&lt;/code&gt; module. Pass the numbers in as &lt;strong&gt;strings&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;decimal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Strings matter here. &lt;code&gt;Decimal(0.1)&lt;/code&gt; would copy the already-imprecise float, and you'd be back to &lt;code&gt;0.1000000000000000055...&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  One more surprise: round() isn't magic either
&lt;/h2&gt;

&lt;p&gt;Now that you know the trick, this one makes sense:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.675&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2.67
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'd expect &lt;code&gt;2.68&lt;/code&gt;. But &lt;code&gt;2.675&lt;/code&gt; is stored as something like &lt;code&gt;2.67499999...&lt;/code&gt;, so it rounds down. Same cause, different symptom.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;What to do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Showing a decimal to a user&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;round(x, 2)&lt;/code&gt; or &lt;code&gt;f"{x:.2f}"&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Checking if two decimals are equal&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;math.isclose(a, b)&lt;/code&gt;, never &lt;code&gt;==&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Money or exact decimal math&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Decimal("0.1")&lt;/code&gt; with strings&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;Reading this is one thing. The rule really sticks after you hit the bug yourself. Open Python and try:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;print(0.1 + 0.2 == 0.3)&lt;/code&gt;. Predict the answer first.&lt;/li&gt;
&lt;li&gt;Find another pair of decimals that doesn't add up cleanly.&lt;/li&gt;
&lt;li&gt;Fix the comparison with &lt;code&gt;math.isclose()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next time Python shows you an error instead of a strange number, here's how to read it: &lt;a href="https://craftstack.hashnode.dev/how-to-read-an-error-message-a-3-step-method-for-python-java-javascript-and-sql" rel="noopener noreferrer"&gt;How to Read an Error Message: A 3-Step Method for Python, Java, JavaScript and SQL&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was first published on the &lt;a href="https://craftstackacademy.com/blog/why-does-0-1-0-2-not-equal-0-3-in-python" rel="noopener noreferrer"&gt;Craftstack Academy blog&lt;/a&gt;. It was written with the help of AI, and every code example was run in Python 3.13 before publishing.&lt;/em&gt;&lt;/p&gt;

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