有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

为什么我的Java数学错了?

在下面的代码中,我看不出T1和T3有什么不同。当然,我的计算器说它们不是

public class longTest {
    public static final long T1 = 24 * 60 * 60 * 1000 * 30;
    public static final long T2 = 24 * 60 * 60 * 1000;
    public static final long T3 = T2 * 30;

    public static void main(String[] args) {

        System.out.println(T1);
        System.out.println(T2);
        System.out.println(T3);
    }
}

那么,我为什么要得到以下结果:

-1702967296
86400000
2592000000

这不仅仅是系统。出来println也在这个示例程序中。当我在eclipse中使用T1并将鼠标移到变量上时,我会得到一个光泽,显示相同的值

java version "1.6.0_33" OSX


共 (3) 个答案

  1. # 1 楼答案

    正如偏执的安卓所说,这是一个溢出问题。要了解T3的不同之处,请参见下文

    public static final long T1 = 24 * 60 * 60 * 1000 * 30;
    

    这里所有的数字都是int,所以这和

    public static final long T1 = (long) (24 * 60 * 60 * 1000 * 30);
    

    int部分溢出,因此对long的隐式转换来得太迟,无法避免精度损失。 在

    public static final long T2 = 24 * 60 * 60 * 1000;
    

    你有相同的数字,但它是一个较小的数字,适合32位int(31位为正值)和64位long

    public static final long T3 = T2 * 30;
    

    它将一个long乘以一个int,64位算术也是如此,这就是为什么它有不同的值
    相当于

    public static final long T3 = T2 * (long) 30;
    

    这里的隐式long足够早,可以防止精度损失

  2. # 2 楼答案

    因为int不能大于2147483647,所以会出现溢出。最终值不在long类型的范围之外,但算术本身将数字视为int,除非您明确声明它们是long

    试试这个:

    public class LongTest {
    
        public static final long T1 = 24L * 60 * 60 * 1000 * 30;
        public static final long T2 = 24L * 60 * 60 * 1000;
        public static final long T3 = T2 * 30;
    
        public static void main(String[] args) {
            System.out.println(T1);
            System.out.println(T2);
            System.out.println(T3);
        }
    }
    
  3. # 3 楼答案

    这是因为在T1中,所有的数字都是整数,所以数学运算是对整数执行的,然后分配给一个长整数T3是将一个Long与一个整数相乘,因此它在进行数学运算时使用Long,结果与预期一致

    要修复它,您需要将数字常量更改为long:

    public class longTest {
       public static final long T1 = 24L * 60L * 60L * 1000L * 30L;
       public static final long T2 = 24 * 60 * 60 * 1000;
       public static final long T3 = T2 * 30;
    
       public static void main(String[] args) {
    
          System.out.println(T1);
          System.out.println(T2);
          System.out.println(T3);
       }
    
    }
    

    要理解为什么会得到一个负数:当它到达最大的正数(2^31-1)时,它会绕到最大的负数(-2^31)并从那里上升。这种包装可能会发生多次,因此当您这样做时:

    public static final int T4 = 100 * 100 * 100 * 100 * 100;// = 1410065408 WHAT!?!?
    

    你得到100亿,这比一个整数所能容纳的还要大。所以,一旦它到达2147483647,它接下来会到达-2147483648,以此类推。。所以,对于100亿美元,它是这样的:

    2147483647(转到底片,我们还有7852516353)

    -2147483648(一直数到整数MAX_INT)

    2147483647(再次转为负片,我们还有3557549057)

    -2147483648(添加剩余的3557549058)

    现在我们有:1410065408