为什么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采取两个步骤:
- 如果浮点数为NaN(§4.2.3),则 转换的第一步是int 或长0
- 否则,如果浮点数不是
无穷大时,浮点值为
四舍五入为整数值V,
使用IEEE 754向零舍入
向零模式四舍五入(§4.2.3)。然后
有两种情况:
- 如果T很长,那么这个整数值可以表示为 长,然后结果第一 步长是长值V
- 否则,如果该整数值可以表示为int, 那么第一步的结果是 int值V
- 否则,以下两种情况之一必须为真:
- 该值必须太小(较大的负值 或负无穷大),以及结果 第一步是最小的 int或int类型的可表示值 长
- 该值必须太大(数值较大的正值 或正无穷大),以及结果 第一步是最大的 int或int类型的可表示值 长。
按照链接,卢克…啊,这些编辑使得评论看起来与第一次发布时如此不同。