为什么这个java表达式会返回否定结果?

时间:2011-12-20 07:08:44

标签: java math date

public static void main (String[] ses) {
    System.out.println(740 * (24 * 60 * 60 * 1000));
}

在谷歌上尝试过,它在科学计算器上给出了不同的结果。

5 个答案:

答案 0 :(得分:5)

因为结果是63,936,000,000,这比你可以存储在Java整数中更多(默认情况下这是因为它们都没有以L开头)。整数只能存储4个字节(32位),该数字需要36位。然后溢出,基本上只使用结果的最后(第一个?)32位。因为这些位的第一个(最后一个?取决于你如何看待它)确定数字是否有符号,当数字实际上被视为整数时,它显示为负数。

这对于计算哈希特别有用,因为我看到的唯一逻辑替代方法是使所有超过最大值的数字等于最大值,我认为我们认为这是一个糟糕的选择。

如果你做了System.out.println(740L * (24 * 60 * 60 * 1000));,它应该使用一个可以存储更大数字的长号。

你会注意到我有问号 - 字节是字节,比特是比特。真正重要的是你如何解释它们。在软件开发社区中存在着争论第一个数字,位或字节的真正含义。将“1234”视为数字。 1是第一位数?大多数普通人都会同意,因为它是在我们看到它时首先写的。但是其他人会认为4是第一个数字,因为为计算目的这样做很方便。 (考虑添加 - 你先在哪里添加?这不是第一个数字吗?)

所以这就是为什么我看起来犹豫不决,就像我先说/最后一样 - 我只是想清楚说明发生了什么。

答案 1 :(得分:2)

所有值都被视为java int类型,处理10位数,而答案(63 936 000 000)包含11位数。如果将其转换为长类型,如

System.out.println( Long.valueOf(740) * (24 * 60 * 60 * 1000 ));

System.out.println( 740 * Long.valueOf((24 * 60 * 60 * 1000 )));

然后你会得到正确答案。

答案 2 :(得分:1)

在java中,int的字节大小为4.您的计算超过这四个字节的值。 所以它会带来一些负面价值。

它被称为整数溢出。

答案 3 :(得分:1)

Java语言规范section 4.2.1给出了整数类型的值范围。

请改用此计算:

System.out.println(740 * 24 * 60 * 60 * 1000L);

L表示1000是long原语(您也可以使用小写L,但在许多字体中看起来太像1)。由于1000是long,因此整个答案变为long - 这称为数字促销,特别是从intlongJLS 5.6)的扩展转换。原始long具有足够的容量来正确存储结果。

与其他数字类型相同。假设你想要一个百分比,那么就像这样编写你的计算:

int i = 99;
System.out.println(i / 100 * 100);

0将被打印到屏幕上。由于所涉及的所有数字都是int基元,因此int不会将零件存储在小数点右侧。

如果您将i除以值{100}的double,则计算将起作用 - 值100被字母'd'标记为double

int i = 99;
System.out.println(i / 100d * 100);

...给出99.0的预期答案。

'我'本来可以成为双重的:

double i = 99;
System.out.println(i / 100 * 100);

......答案仍然是正确的。

答案 4 :(得分:0)

当你简单地写出这样的计算时,Java会将输入值视为整数,从而返回一个整数。

  

(740 *(24 * 60 * 60 * 1000))= 63,936,000,000

所以它会尝试以整数存储63936000000。问题是,整数数据类型不是为了存储高于2 ^ 32 / 2-1 = 2,147,483,647的任何东西而设计的。这导致了所谓的Integer Overflow

因此,您可以手动指定允许更大数字的类型,而不是让Java猜测您的数据类型。在The Java Tutorial: Primitive Data Types中,您可以看到数据类型及其限制的列表。在这里,您会注意到long符合您的需求,因为它允许多达2 ^ 64个不同的值而不是2 ^ 32。

那么为什么这个数字呢?

如果您运行程序,则会获得 -488509440 。这是因为,如上所述,整数数据类型不允许存储超过32位。剩下的就被切断了。

因此, 63936000000 的二进制表示为 111011100010111000011111000000000000 。这需要36位,因此前四个被切断。这留下了 11100010111000011111000000000000 ,其中十进制为 3806457856

整数数据类型使用2 ^ 32中所有值的前半部分用于负值,而后半部分(减1,因为我们还需要值0)用于正值(因此为什么你只能存储一个数量高达2 ^ 32 / 2-1)。

所以,如果我们从数字中减去32 ^ 2,我们最终会得到

3806457856 - 4294967296 = -488509440