title: Buggy floating point handling in Visual Studio?
body: <p><strong>There's an update in the end!</strong></p>
  
  <p>I have a little story.</p>
  
  <p>I wanted to calculate the machine epsilon (the largest epsilon > 0 satisfying condition 1.0 + epsilon = 1.0) in a C program compiled by MS Visual Studio 2008 (running on Windows 7 in a 64 bit PC). Since I know that double and float have different precision I wanted to see the answer for both. For that reason I constructed the following program:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  typedef double float_type;
  int main()
  {
    float_type eps = 1.0;
    while ((float_type) 1.0 + eps / (float_type) 2.0 &gt; (float_type) 1.0)
      eps = eps / (float_type) 2.0;
    printf("%g\n", eps);
    return 0;
  }
  </code></pre>
  
  <p>I was quite surprised to see that it gave the same answer for both types double and float: 2.22045e-16. That was strange since double occupies twice more memory than float and should be more precise. After that I looked into <a href="http://en.wikipedia.org/wiki/Machine_epsilon" rel="nofollow">Wikipedia</a> and took a sample code from there:</p>
  
  <pre><code>    #include &lt;stdio.h&gt;
      int main(int argc, char **argv)
      {
        float machEps = 1.0f;
        do {
          machEps /= 2.0f;
        } while ((float)(1.0 + (machEps/2.0)) != 1.0);
        printf( "\nCalculated Machine epsilon: %G\n", machEps );
        return 0;
     }
  </code></pre>
  
  <p>I was even more surprised when it worked correctly! After some attempts to understand the fundamental difference between the two programs I figured out the following fact: my program (the first one) starts to give the corrent answer for float (1.19209e-07) if I change the loop condition to</p>
  
  <pre><code>  while ((float_type) (1.0 + eps / (float_type) 2.0) &gt; (float_type) 1.0)
  </code></pre>
  
  <p>Well, that is a mystery you'd say. Oh, the real mystery is the following. Compare:</p>
  
  <pre><code>  while ((float) (1.0 + eps / 2.0f) &gt; 1.0f) 
  </code></pre>
  
  <p>which gave the correct answer (1.19209e-07) and</p>
  
  <pre><code>  while ((float) (1.0f + eps / 2.0f) &gt; 1.0f)
  </code></pre>
  
  <p>which gave answer which is incorrect for float and correct for double (2.22045e-16).</p>
  
  <p>In fact that is totally wrong, the result should have been opposite. That is because by default constants like 1.0 are treated as double by the compiler (according to the standard) and if it is present in an arithmetic expression then all other operands are promoted to double. Conversely, when I write 1.0f all operands are float and no promotion should take place. And yet I get a completely different result.</p>
  
  <p>After all these tests I tried to compile run the programs on Linux using gcc. No surprise, it printed exactly what I expected (correct answers). So I now guess that this is Visual Studio bug. To make you all laugh (if there are any people who have read my post till that moment what is doubtful ^_^) I will give you another comparison:</p>
  
  <pre><code>float c = 1.0;
  while ((float) (c + eps / 2.0f) &gt; 1.0f)
  </code></pre>
  
  <p>This does not work properly in VS, but...</p>
  
  <pre><code>const float c = 1.0;
  </code></pre>
  
  <p>gives the correct answer of 1.19209e-07.</p>
  
  <p>Please somebody tell me if I am right that the root of the problem is a buggy VS 2008 compiler (can you confirm the bug on your machines?). I would be also  grateful if you tested the case in a newer version: MS VS 2010. Thanks.</p>
  
  <p><strong>UPDATE.</strong>
  With MS Visual Studio 2013 the first program I mentioned works without unexpected results -- it gives appropriate answers for float and double. I checked this with all floating point models (precise, strict and fast) and nothing changed. So it indeed seems that VS 2008 was buggy in this case.</p>