我认为不需要多解释,为什么以下计算结果为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
答案 0 :(得分:11)
整数2147483647的二进制表示如下:
componentWillMount() {
this.setState({loading: true});
ajaxCall().then(responses => {
// process response
this.setState({loading: false});
});
}
将其与自身相乘会产生数字4611686014132420609,其二进制表示形式为:
01111111 11111111 11111111 11111111
这对于只有32位的00111111 11111111 11111111 11111111 00000000 00000000 00000000 00000001
类型来说太大了。 int
的乘法仅作为整数乘法完成,而不管分配结果的变量类型(可能会进行扩展转换,但仅在乘法后)。
因此,结果只是切断了不适合32位的所有位,只留下以下结果:
a * b
这只是值1。
如果要保留信息,则必须使用64位的00000000 00000000 00000000 00000001
类型进行乘法运算:
long
如果您需要更多位进行计算,可以考虑BigInteger
(对于整数)或BigDecimal
(对于十进制数)。
答案 1 :(得分:5)
2147483647 * 2147483647 = 4611686014132420609
在Hexa = 3FFFFFFF 00000001中,截断后只剩下00000001,代表1。
答案 2 :(得分:4)
首先,三次尝试都给出相同答案的原因是它们都在执行32位乘法并且乘法溢出,导致“信息丢失”。在将RHS 1 表达式的值分配给LHS上的变量之前,发生信息溢出/丢失。
在第二种和第三种情况下,您可以使用64位或浮点来计算表达式:
int c = a * b;
long d = ((long) a) * b;
double e = ((double) a) * b;
你不会溢出。
至于为何在32位情况下出现溢出,这很简单。结果大于32位。其他答案解释了为什么答案是1
。
只是为了好玩,这是一个非正式的证明。
假设我们正在谈论一个模数系统,其数字范围为2 N-1 至2 N-1 - 1.在这样的数字系统中,对于所有整数X,X * 2 N 映射到零...
如果我们自己乘以最大值,我们得到
(2 N-1 - 1)*(2 N-1 - 1)
- > 2 2N-2 - 2 * 2 N-1 + 1
- > 2 2N-2 - 2 N + 1
现在将其映射到原始范围:
2 2N-2 映射到0
2 N 映射0
1映射到1
0 + 0 + 0 - > 1
1 - LHS ==左手边,RHS ==右手边。
答案 3 :(得分: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
答案 4 :(得分:0)
<强>因为:强>
2147483647 * 2147483647 = 4611686014132420609
整数容量= 4294967295
4611686014132420609%4294967295 = 1
答案 5 :(得分:-2)
整数只有3字节的内存分配以及双倍的8字节内存分配你的乘法是如此之大,只有它的启动它有(0000 0001)2 = 1