Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Because <code>0.1</code> isn't 0.1; that value isn't representable in double precision, so it gets rounded to the nearest double-precision number, which is exactly:</p> <pre><code>0.1000000000000000055511151231257827021181583404541015625 </code></pre> <p>When you call <code>fmod</code>, you get the remainder of division by the value listed above, which is exactly:</p> <pre><code>0.0999999999999999500399638918679556809365749359130859375 </code></pre> <p>which rounds to <code>0.1</code> (or maybe <code>0.09999999999999995</code>) when you print it.</p> <p>In other words, <code>fmod</code> works perfectly, but you're not giving it the input that you think you are.</p> <hr> <p><strong>Edit:</strong> Your own implementation gives you the correct answer because it is <em>less accurate</em>, believe it or not. First off, note that <code>fmod</code> computes the remainder without any rounding error; the only source of inaccuracy is the representation error introduced by using the value <code>0.1</code>. Now, let's walk through your implementation, and see how the rounding error that it incurs exactly cancels out the representation error.</p> <p>Evaluate <code>a - floor(a/n) * n</code> one step at a time, keeping track of the exact values computed at each stage:</p> <p>First we evaluate <code>1.0/n</code>, where <code>n</code> is the closest double-precision approximation to <code>0.1</code> as shown above. The result of this division is approximately:</p> <pre><code>9.999999999999999444888487687421760603063276150363492645647081359... </code></pre> <p>Note that this value is not a representable double precision number -- so it gets <em>rounded</em>. To see how this rounding happens, let's look at the number in binary instead of decimal:</p> <pre><code>1001.1111111111111111111111111111111111111111111111111 10110000000... </code></pre> <p>The space indicates where the rounding to double precision occurs. Since the part after the round point is larger than the exact half-way point, this value rounds up to exactly <code>10</code>.</p> <p><code>floor(10.0)</code> is, predictably, <code>10.0</code>. So all that's left is to compute <code>1.0 - 10.0*0.1</code>.</p> <p>In binary, the exact value of <code>10.0 * 0.1</code> is:</p> <pre><code>1.0000000000000000000000000000000000000000000000000000 0100 </code></pre> <p>again, this value is not representable as a double, and so is rounded at the position indicated by a space. This time it rounds down to exactly <code>1.0</code>, and so the final computation is <code>1.0 - 1.0</code>, which is of course <code>0.0</code>.</p> <p>Your implementation contains two rounding errors, which happen to exactly cancel out the representation error of the value <code>0.1</code> in this case. <code>fmod</code>, by contrast, is <em>always</em> exact (at least on platforms with a good numerics library), and exposes the representation error of <code>0.1</code>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload