为什么CLR会使Int32.MaxValue溢出->;单个->;Int32,JVM不在哪里?

为什么CLR会使Int32.MaxValue溢出->;单个->;Int32,JVM不在哪里?,jvm,floating-point,clr,int,Jvm,Floating Point,Clr,Int,我在往返Int32.MaxValue到系统时遇到意外结果。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时,会抛

我在往返
Int32.MaxValue
系统时遇到意外结果。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
时,会抛出一个
overflowxpetion
。很公平

然而,当我调查这个问题时,我用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\u VALUE
以避免溢出?

这种情况由Java语言规范的一部分明确处理:

一种变窄的变换 将浮点数转换为整数 类型T采取两个步骤:

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

  • 按照链接,卢克…啊,这些编辑使得评论看起来与第一次发布时如此不同。