繁体   English   中英

为什么此Java表达式返回否定结果?

[英]why does this java expression return a negative result?

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

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

因为结果是63,936,000,000,这超出了您可以存储在Java整数中的值(默认情况下,这是因为它们都不以L开头)。 一个整数只能存储4个字节(32位),而该数字将需要36位。 然后它溢出,基本上只使用结果的最后(第一个?)32位。 由于这些位中的第一个(最后一个?取决于您的外观)决定了一个数字是否带符号,因此当该数字再次实际被视为整数时,它将显示为负数。

这对计算哈希值特别有用,因为我看到的唯一合乎逻辑的选择是使最大值上的所有数字都等于最大值,我认为我们可以同意这是一个糟糕的选择。

如果是System.out.println(740L * (24 * 60 * 60 * 1000)); 它应该使用可以存储更大数字的长整数。

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

因此,这就是为什么我在说第一个/最后一个词时犹豫不决-我只想弄清楚发生了什么。

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

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

要么

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

那么您将得到正确的答案。

在Java中,int的字节大小为4。您的计算超出了这四个字节的值。 因此它抛出了一些负值。

这称为整数溢出。

Java语言规范的第4.2.1节提供了整数类型的值范围。

请改用此计算:

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

L表示1000是一个long原语(您也可以使用小写的L,但是在许多字体中看起来太像1)。 由于1000很long所以整个答案就很long -这就是所谓的数值提升,特别是从intlong转换( JLS 5.6 )。 原语long具有足够的容量来正确存储结果。

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

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

0将被打印到屏幕上。 由于涉及的所有数字都是int原语,因此您将获得99/100 = 0,因为int不会将小数部分存储在小数点右边。

如果分割i通过一个double与100的值计算将工作-该值100被标记为double用“D”字母:

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

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

我本可以成为双打:

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

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

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

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

因此,它将尝试以整数形式存储63936000000。 问题是,整数数据类型不能存储大于2 ^ 32 / 2-1 = 2,147,483,647的任何数据。 这导致所谓的Integer Overflow

因此,您可以手动指定允许更大数量的类型,而不是让Java猜测您的数据类型。 Java教程:原始数据类型中 ,您可以看到数据类型及其限制的列表。 在这里,您会发现long可以满足您的需求,因为它允许多达2 ^ 64个不同的值,而不是2 ^ 32。

那么,为什么要那个数字呢?

如果运行程序, 则将得到-488509440 如前所述,这是因为整数数据类型不允许您存储超过32位。 其余的被切断。

因此, 639.36 亿的二进制表示形式111011100010111000011111000000000000 这需要36位,因此前四个被切断。 这就给我们11100010111000011111000000000000这在十进制是3806457856。

整数数据类型将2 ^ 32中所有值的前半部分用作负值,将后半部分(减去1,因为我们也需要值0)用于正值(因此为什么只能存储一个大数)如2 ^ 32 / 2-1)。

因此,如果我们从数字中减去32 ^ 2,我们将得到

3806457856-4294967296 = -488509440

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM