为什么我的Java数学错了?

为什么我的Java数学错了?,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(St

在下面的代码中,我看不出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
在这个示例程序中也不仅仅是System.out.println。当我在eclipse中使用T1并将鼠标移到变量上时,我会得到一个光泽,显示相同的值

java版本“1.6.0_33”OSX


因为
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);
    }
}

这是因为在
T1
中,所有数字都是整数,因此对整数执行数学运算,然后将其分配给一个长整数
T3
将一个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

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

public static final long T1 = 24 * 60 * 60 * 1000 * 30;
这里的所有数字都是
int
s,因此这与

public static final long T1 = (long) (24 * 60 * 60 * 1000 * 30);
int
部分溢出,因此对
long
的隐式转换来得太迟,无法避免精度损失。 在

您有相同的数字,但它是一个较小的数字,适用于32位
int
(31位表示正值)和64位

public static final long T3 = T2 * 30;
这将
long
乘以
int
,64位算术也是如此,这就是为什么它有不同的值。
相当于

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

此处的隐式
long
足够早,可以防止精度损失。

可以使用
L
而不是
L
来表示
long
。在许多终端字体中,小写字母
l
看起来非常像
1
,而
l
则不是。实际上,这太好了,太公开了静态最终长T1=24L*60*60*1000*30;“Java从根本上打破了数学吗?”——当然不是@Shark整数溢出。直到有人转换该值,该值才会变为长值。
public static final long T3 = T2 * (long) 30;