现在signed_int最大值为2147483647,即2^31,1位为符号位,因此
当我运行long a = 2,147,483,647 + 1;
时
它给出a = -2,147,483,648
作为答案。。这很好。但是,24*60*60*1000*1000 = 86400000000
(实际上)。。。在java中,24*60*60*1000*1000 it equals to 500654080
。。我知道这是因为在integer中溢出,但是什么处理导致了这个值,Java使用了什么逻辑来获得这个数字。我也参考了这里。
乘法像一样从左到右执行
int x = 24 * 60;
x = x * 60;
x = x * 1000;
x = x * 1000;
前3个运算产生86400000,仍然适用于Integer.MAX_VALUE。但最后一个运算产生的86400000000是十六进制的0x141dd76000。4以上的字节被截断,得到0x1dd76000。如果我们打印
System.out.println(0x1dd76000);
结果将是
500654080
这是非常微妙的:在编写long a = 2147483647 + 1
时,由于提供了int
文字,因此首先使用int
计算右手边。但在转换为long
之前,它将循环到负值(由于溢出)。所以从int
升级到long
对你来说太晚了。
为了避免这种行为,你需要通过后缀L.来将至少一个论点提升为长文字
这适用于所有使用字面值的算术运算(即乘法):您需要将其中一个字面值提升为长类型。
你的乘法答案是500654080,这一事实可以从中看出
long n = 24L*60*60*1000*1000;
long m = n % 4294967296L; /* % is extracting the int part so m is 500654080
n.b. 4294967296L is 2^32 (using OP notation, not XOR). */
这里发生的事情是,你正在使用int类型"昼夜不停"。是的,你正在丢失进位位,但这与乘法无关。
因为int的范围是-2147483648到2147483647。因此,当您继续添加数字并超过最大限制时,它会从最左边的数字开始增益,即-2147483648,因为它是一个循环。你已经在你的问题中提到了。
类似地,当您计算24*60*600*1000时,根据数学计算结果应为86400000000。
但实际情况如下:
86400000000可以写为2147483647+2147483647%2147483647+214783647+21474833647+。。36次+500654080
因此,在将21474833647添加40次后,结果为0,然后留下500654080最终导致500654080。
我希望你清楚。
在您的multiplicatoin中添加L。如果你加上L,那么它在长范围内乘以你,否则在溢出的整数范围内。试着像这样相乘。
24L*60*60*1000*1000
这给了你一个正确的答案。
整数的长度为32位。为了简单起见,让我们以一个4位长的数字为例。
其最大正值为:
0111 = 7 (first bit is for sign; 0 means positive, 1 means negative)
0000 = 0
其min负值为:
1111 = -8 (first bit is for sign)
1000 = -1
现在,如果我们称这种类型为fbit
,那么fbit_max
等于7。
fbit_max + 1 = -8
because bitwise 0111 + 1 = 1111
因此,fbit_min
到fbit_max
的跨度为16。从-8到7。
如果您将类似7*10
的东西相乘并将其存储在fbit
中,结果将是:
fbit number = 7 * 10 (actually 70)
fbit number = 7 (to get to from zero to max) + 16 (min to max) + 16 (min to max) + 16 (min to max) + 15 (the rest)
fbit number = 6
24*60*60*1000*1000 = 86400000000
使用MOD如下:86400000000%214783648=500654080