【问题标题】:Casting result of multiplication two positive integers to long is negative value将两个正整数相乘转换为long的结果为负值
【发布时间】:2012-10-12 15:03:08
【问题描述】:

我有这样的代码:

int a = 629339;
int b = 4096;
long res = a*b;

结果是-1717194752 但是如果我将一个手动转换添加到 long long res = ((long)a)*b;long res = (long) a*b;,结果是正确的 2577772544 谁能解释一下它是如何工作的。

【问题讨论】:

    标签: java android jvm dalvik


    【解决方案1】:

    您必须将赋值语句分解为多个部分才能了解正在执行的操作:

    long res = a*b;
    

    第一步是获取ab的值。

    第 2 步是评估 a * b。因为ab 都是ints,所以这是一个int 乘法。所以我们将629339 乘以629339 即为2577772544。 不幸的是,2577772544 大于 Java 可能的最大 int 值...所以乘法运算会悄悄地溢出 ...而我们得到的是-1717194752

    第 3 步,我们将 RHS 的值分配给 LHS。由于 RHS 是 int 而 LHS 是 float,JLS 说我们执行 原始加宽 转换......这只是将 -1717194752 转换为具有相同值的 long。然后将扩大的值分配给res


    为了得到您期望的答案,我们必须强制使用long 算术执行乘法运算。例如:

    long res = ((long) a) * b;
    

    在这种情况下,我们将longint 相乘,这是通过将int 扩大到long 并执行long 乘法来处理的。这不再溢出(因为2577772544 远低于最大的long 值),所以当我们最终将值分配给res 时,它就是您所期望的数字。

    【讨论】:

    • 据我所知,在 C++ 中,所有算术运算的结果都被转换为结果类型。 Java 不会自动执行此操作/
    • 在 Java 中,结果类型的扩展发生在最终赋值中,不会影响 RHS 表达式的计算方式。
    • 另外,我的 C++ 生锈了,但我相信 C++ 在这方面的行为与 Java 相同。
    • С++ 行为取决于您使用的编译器。
    • 叹息...感谢您提醒我放弃 C 和 C++ 的原因之一
    【解决方案2】:

    a*b 是整数,而不是长整数。

    因为它只是一个整数,它已经绕过了 32 位的限制。
    将此整数转换回 long 不会神奇地恢复该数据。

    【讨论】:

      【解决方案3】:
      long res = a*b;
      

      a*b 将被视为整数,除非您在结束(或)转换时添加“l”。

      根据java tutorial

      int 数据类型是一个 32 位有符号二进制补码整数。它的最小值为 -2,147,483,648,最大值为 2,147,483,647(含)。对于整数值,此数据类型通常是默认选择,除非有理由(如上述)选择其他类型。

      【讨论】:

      • 据我了解,java 不会自动将类型转换为结果类型?
      • 是的,没错。有确定结果类型的规则。让我看看能否为您找到该文档。
      猜你喜欢
      • 2014-03-20
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-13
      相关资源
      最近更新 更多