【问题标题】:Really confused by java data type in this specific case [duplicate]在这种特定情况下,java数据类型真的很困惑[重复]
【发布时间】:2016-05-11 08:03:11
【问题描述】:
public class Test {
        public static void main(String [] s) {
            int x = 99999;
            long y = 99999;

            long res = x * x;
            System.out.println("x^2 = " + res);
            res = y * y;
            System.out.println("y^2 = " + res);
        }
    }



 Output: 
    x^2 = 1409865409
    y^2 = 9999800001

看到上述代码段的输出,我真的很困惑。我希望得到相同(正确)的答案,但这里 x^2 实际上是错误的!

【问题讨论】:

  • 您遇到了溢出。一旦x 达到Integer.MAX_VALUE 的值,将+1 添加到x 将导致x 蜂鸣Integer.MIN_VALUE
  • 在第一种情况下,您将两个整数相乘,然后转换为长整数,在第二种情况下,您将两个整数相乘

标签: java long-integer


【解决方案1】:

99999 * 99999 = 1001010100000010001101011011000001 二进制(如果你计算这些,你会发现你需要 34 位来表示内存中的这个数字)。

int32 位 长,因此两个 MSB 被剪掉。

结果是01010100000010001101011011000001b = 1409865409 十进制。

将此值分配给 64 位长不会改变结果,两个整数相乘得到整数作为结果。

【讨论】:

    【解决方案2】:

    因为首先x * xint 空间中完成,然后才将结果放入long。因此,即使long 变量足够大以保存结果,在将结果放入long 之前,它首先被计算为int 乘积,结果被截断,因为它不适合int

    【讨论】:

      【解决方案3】:

      那是因为你乘以integersx * x,结果就是integer(临时变量,我们这里说的是x * x运算的结果,不是res =部分)。由于结果会比Integer.MAX_VALUE 大,你会得到一些“奇怪”的数字。然后将该数字放入long 类型的变量中。

      这是解决此问题的方法:

      long res = 1l * x * x;
      

      现在,它会计算1l * x,因为第一个数字是long,它会计算为long,然后乘以x,同样,因为第一个数字是long,所以结果将是long,那么这个结果将被放入变量res

      以类似的方式解决丢失小数的问题,例如:

      int a = 10;
      int b = 3;
      double d = a / b;
      

      结果将是3.0。但是,如果你这样做:

      double d = (1d *a) / b;
      d = a / (b * 1d);
      d = (double) a / d; 
      

      两者都是3.3333333333333335(这个5,那是另一个问题......)。 此外,对其中一个变量进行双重转换也可以(感谢@Aconcagua)。

      【讨论】:

      • 为什么要与常数相乘 - 您只需将第一个(或第二个...)操作数分别转换为 long 或 double。
      • 对……不知道,习惯了这样做,无缘无故……
      • 您以这种方式引入了剩余运算(乘法)。不过,它应该被优化掉,但是当你有一个替代方案时,你依赖于优化,而不必进一步依赖任何东西......
      • 不知道,如果常识,但此外,我个人认为铸造更明确/清楚地表达意图。
      • 如果是常数,则变量不应该消耗任何内存...两种变体都同样快,if 乘法被优化掉了,否则你会得到一个额外的操作(在双重情况下的 FPU)。然而,前者是我对任何可行的 JIT 的期望,所以实际上,你应该是对的......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-10
      • 1970-01-01
      • 1970-01-01
      • 2019-11-28
      • 1970-01-01
      • 2022-01-14
      相关资源
      最近更新 更多