为什么CLR溢出Int32.MaxValue - >单 - > Int32,JVM没有?

时间:2010-11-01 22:19:39

标签: jvm floating-point clr int

我在向Int32.MaxValue进行往返System.Single时遇到意外结果:

Int32 i = Int32.MaxValue;
Single s = i;
Int32 c = (Int32)s;

Debug.WriteLine(i); // 2147483647
Debug.WriteLine(c); // -2147483648

我意识到它必须溢出,因为Single在有效位数中没有足够的位来保存Int32值,并且它会向上舍入。当我在IL中将conv.r4更改为conv.r4.ovf时,会抛出OverflowExcpetion。足够公平......

然而,在我调查这个问题时,我在java中编译了这段代码并运行它并得到以下内容:

int i = Integer.MAX_VALUE;
float s = (float)i;
int c = (int)s;

System.out.println(i);  // 2147483647
System.out.println(c);  // 2147483647

我对JVM知之甚少,但我想知道它是如何做到的。这似乎不那么令人惊讶,但是在四舍五入到2.14748365E9后它如何保留额外的数字?它是否保留某种内部表示,然后在转回int时替换它?或者只是向下舍入到Integer.MAX_VALUE以避免溢出?

1 个答案:

答案 0 :(得分:3)

这种情况由Java语言规范的§5.1.3显式处理:

  

a的缩小转换   浮点数到一个整数   T型需要两个步骤:

     
      
  1. 在第一步中,转换浮点数   要么长,要么长,要么   一个int,如果T是byte,short,char或   int,如下:   
        
    • 如果浮点数是NaN(§4.2.3),则结果为   转换的第一步是int   或者长0。
    •   
    • 否则,如果浮点数不是   无穷大,浮点值是   四舍五入为整数值V,   使用IEEE 754向零舍入   圆向零模式(§4.2.3)。然后   有两种情况:   
          
      • 如果T很长,则此整数值可以表示为a   很久,然后是第一个结果   step是长值V。
      •   
      • 否则,如果此整数值可以表示为int,   然后第一步的结果是   int值V.
      •   
    •   
    • 否则,以下两种情况之一必须为真:   
          
      • 该值必须太小(大幅度的负值)   或负无穷大),结果   第一步是最小的   int或类型的可表示值   长。
      •   
      • 该值必须太大(大幅度的正值)   或正无穷大),结果   第一步是最大的   int或类型的可表示值   长。
      •   
    •   
  2.