为什么最大整数乘法的结果是 1

问题描述 投票:0回答:6

我想不需要太多解释,为什么下面的计算给出的结果是1?

int a = 2147483647;
int b = 2147483647;

int c = a * b;
long d = a * b;
double e = a * b;

System.out.println(c);  //1
System.out.println(d);  //1
System.out.println(e);  //1.0
java int
6个回答
13
投票

整数2147483647的二进制表示如下:

01111111 11111111 11111111 11111111

将其与自身相乘得到数字 4611686014132420609,其二进制表示为:

00111111 11111111 11111111 11111111 00000000 00000000 00000000 00000001

这对于只有 32 位的

int
类型来说太大了。
a * b
的乘法仅作为整数乘法完成,无论结果分配到的变量的类型如何(这可能会进行扩大转换,但仅在乘法之后)。

所以,结果只是截掉所有不适合32位的位,只留下以下结果:

00000000 00000000 00000000 00000001

这就是值 1。

如果要保留信息,必须与 64 位的

long
类型进行乘法:

long a = 2147483647;
long b = 2147483647;
long mult = a * b;

System.out.println((int) mult);     // 1
System.out.println(mult);           // 4611686014132420609
System.out.println((double) mult);  // 4.6116860141324206E18

如果您需要更多位进行计算,您可以考虑

BigInteger
(对于整数)或
BigDecimal
(对于小数)。


6
投票

2147483647 * 2147483647 = 4611686014132420609

十六进制 = 3FFFFFFF 00000001,截断后只剩下 00000001 代表 1。


4
投票

首先,三次尝试都给出相同答案的原因是,它们都在执行 32 位乘法,并且乘法溢出,导致“信息丢失”。 信息溢出/丢失发生在将 RHS1 表达式的值分配给 LHS 上的变量之前

在第二种和第三种情况下,您可以使用 64 位或浮点来计算表达式:

int c = a * b; long d = ((long) a) * b; double e = ((double) a) * b;
并且你不会溢出。

至于为什么在 32 位情况下会出现溢出,很简单。 结果大于 32 位。 其他答案解释了为什么答案是

1

只是为了好玩,这是一个非正式的证明。

假设我们正在讨论一个模数系统,其数字范围为 2

N-1 到 2N-1 - 1。在这样的数字系统中,X * 2N 映射到零......对于所有整数 X.

如果我们将最大值与其本身相乘,我们会得到

(2

N-1 - 1) * (2N-1 - 1)

-> 2

2N-2 - 2 * 2N-1 + 1

-> 2

2N-2 - 2N + 1

现在将其映射到原始范围:

2

2N-2 映射到 0

2

N 地图 0

1 映射到 1

0 + 0 + 0 -> 1


1 - LHS == 左侧,RHS == 右侧。


1
投票
您所看到的只是整数溢出的结果,它遵循以下规则:

Integer.MAX_VALUE + 1 = Integer.MIN_VALUE

了解正在发生的情况的一种方法是将 Java 的

int

 类型设计为从 
-7
7
,仍然适用相同的规则。  让我们看看当我们相乘时会发生什么 
7*7
:

7 + 7 = 14 -> -2 (7 x 2) -2 + 7 = 5 (7 x 3) 5 + 7 = 12 -> -4 (7 x 4) -4 + 7 = 3 (7 x 5) 3 + 7 = 10 -> -6 (7 x 6) -6 + 7 = 1 (7 x 7, one is leftover)

您的代码中也发生了同样的事情,

2147483647

根据以下情况溢出:

2147483647 + 1 = -2147483648
    

0
投票

因为:

2147483647 * 2147483647 = 4611686014132420609

整数容量=4294967295

4611686014132420609% 4294967295 = 1


-2
投票
整数只有 3 字节内存分配,而双精度有 8 字节内存分配,你的乘法比它只给出的起始值大,它有 (0000 0001)2 = 1

© www.soinside.com 2019 - 2024. All rights reserved.