Determine how many decimal digits of a float are precise
<p>In my real-life problem, I multiply the size of a widget, with a <code>size_hint</code> which can be anything from <code>0.</code> to <code>1.</code>. Assuming the minimum size of a widget is <code>0</code> and the max size is <code>10,000</code>, on which digit should I expect the error to occur, when I multiply <code>size * size_hint</code>? </p>

<p>For example* on <code>0.1</code> the error occurs on the.. </p>

<pre><code>&gt;&gt;&gt; from decimal import Decimal
&gt;&gt;&gt; Decimal.from_float(.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
#                           ^ 
#                           |_ here 
</code></pre>

<p>.. 18th decimal digit.</p>

<p>On the other hand, the error below occurs on the 14th decimal </p>

<pre><code>&gt;&gt;&gt; 1001*.2
200.20000000000002
</code></pre>

<p><strong>Questions</strong>:   </p>

<ul>
<li>Is there a way to determine on which exactly decimal digit the error will occur? </li>
<li>Is there a difference between Python 2 and Python 3?</li>
</ul>

<p>Using decimals instead of floats is not a option, and that both <code>size</code> and <code>size_hint</code> are provided by the user.</p>

<hr>

<p>*<sub>  I used <a href="https://docs.python.org/3.5/library/fractions.html" rel="nofollow"><code>Fraction</code></a> since <code>&gt;&gt;&gt; 0.1</code> is displayed as.. <code>0.1</code> in the console, but I think this is related to how it's printed, not how it's stored. </sub></p>

<p>I'd recommend you take a read to <a href="https://docs.python.org/3/whatsnew/3.5.html#pep-485-a-function-for-testing-approximate-equality" rel="nofollow">pep485</a></p>

<p>Using <code>==</code> operator to compare floating-point values is not the right way to go, instead consider using <a href="https://docs.python.org/3/library/math.html#math.isclose" rel="nofollow">math.isclose</a> or <a href="https://docs.python.org/3/library/cmath.html#cmath.isclose" rel="nofollow">cmath.isclose</a>, here's a little example using your values:</p>

<pre><code>try:
    from math import isclose

    v1 = 101 * 1 / 5
    v2 = 101 * (1 / 5)
except:
    v1 = float(101) * float(1) / float(5)
    v2 = float(101) * (float(1) / float(5))

    def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
        return abs(a - b) &lt;= max(rel_tol * max(abs(a), abs(b)), abs_tol)

print("v1==v2 {0}".format(v1 == v2))
print("isclose(v1,v2) {0}".format(isclose(v1, v2)))
</code></pre>

<p>As you can see, I'm explicitly casting to float in <strong>python 2.x</strong> and using the function provided in the documentation, with <strong>python 3.x</strong> I just use directly your values and the provided function from math module.</p>

python floating-point precision significant-digits