【问题标题】:Why does the CLR overflow an Int32.MaxValue -> Single -> Int32, where the JVM does not?为什么 CLR 会溢出 Int32.MaxValue -> Single -> Int32,而 JVM 不会?
【发布时间】:2010-11-01 22:19:38
【问题描述】:

我在将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 以避免溢出?

【问题讨论】:

    标签: jvm floating-point clr int


    【解决方案1】:

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

    a 的缩小转换 浮点数转换为整数 type T 需要两个步骤:

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

    【讨论】:

    • 点击链接,卢克...
    • 啊,这些编辑如何使 cmets 看起来与第一次发布时如此不同。
    猜你喜欢
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-04
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    相关资源
    最近更新 更多