title: Why does the CLR overflow an Int32.MaxValue -> Single -> Int32, where the JVM does not?
body: <p>I ran into an unexpected result in round-tripping <code>Int32.MaxValue</code> into a <code>System.Single</code>:</p>
  
  <pre><code>Int32 i = Int32.MaxValue;
  Single s = i;
  Int32 c = (Int32)s;
  
  Debug.WriteLine(i); // 2147483647
  Debug.WriteLine(c); // -2147483648
  </code></pre>
  
  <p>I realized that it must be overflowing, since <code>Single</code> doesn't have enough bits in the significand to hold the <code>Int32</code> value, and it rounds up. When I changed the <code>conv.r4</code> to <code>conv.r4.ovf</code> in the IL, an <code>OverflowExcpetion</code> is thrown. Fair enough...</p>
  
  <p>However, while I was investigating this issue, I compiled this code in java and ran it and got the following:</p>
  
  <pre><code>int i = Integer.MAX_VALUE;
  float s = (float)i;
  int c = (int)s;
  
  System.out.println(i);  // 2147483647
  System.out.println(c);  // 2147483647
  </code></pre>
  
  <p>I don't know much about the JVM, but I wonder how it does this. It seems much less surprising, but how does it retain the extra digit after rounding to 2.14748365E9? Does it keep some kind of internal representation around and then replace it when casting back to <code>int</code>? Or does it just round down to <code>Integer.MAX_VALUE</code> to avoid overflow?</p>