我在java中乘以2
非常大的数字,但乘法输出似乎有点奇怪
的代码
long a = 2539586720l;
long b = 77284752003l;
a*=b;
System.out.println(a);
a=(long)1e12;
b=(long)1e12;
a*=b;
System.out.println(a);
输出:
-6642854965492867616
2003764205206896640
在第一种情况下,为什么结果是否定的,如果是因为溢出,那么第二种结果为何是积极的?请解释一下这种行为? Code
Edit:
我正在使用mod=100000000009
操作仍然是否定的?
a = ((a%mod)*(b%mod))%mod
答案 0 :(得分:2)
对于long
,您得到的结果通常是溢出问题:java为数字分配63
位,为符号分配最高有效位(MSB)(0
对于正值,对于负值,1
,所以总共64
位。
知道,Long.MAX_VALUE + 1
等于-9223372036854775808
,因为Long.MAX_VALUE
= 2^63 - 1
= 9223372036854775807
= 0x7fffffffffffffffL
所以如果我们添加{{1}我们得到1
= 0x8000000000000000L
= Long.MIN_VALUE
= -2^63
。在这种情况下,MSB从-9223372036854775808
切换到0
,因此结果为负,这实际上是您在第一个用例中得到的结果。
如果MSB设置为1
并且您通过某些计算导致新的溢出,它将再次切换到1
(因为我们只保留第一个0
位)所以结果将是正面的,这实际上是你在第二个用例中得到的结果。
为避免您需要使用BigInteger
。
答案 1 :(得分:1)
是。这是一个溢出问题。长度为8个字节,range goes from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
如果你想增加真正的大数字。使用BigInteger
import java.math.*;
public static void main(String[] args){
BigInteger bi1, bi2, bi3;
bi1 = new BigInteger("2539586720"); //or 1000000000000
bi2 = new BigInteger("77284752003");
// multiply bi1 with bi2 and assign result to bi3
bi3 = bi1.multiply(bi2);
String str = bi1 + " * " + bi2 + " = " +bi3;
//Multiplication result is 2539586720 * 77284752003 = 196271329845312200160
}
答案 2 :(得分:0)
如果整数乘法溢出,则结果是数学乘积的低阶位,如某些足够大的二进制补码格式所示。因此,如果发生溢出,则结果的符号可能与两个操作数值的数学乘积的符号不同。
这就是您获得负值并且与输入数字没有任何关联的原因。这是因为Java中的long
只能表示从-2 ^ 63到(2 ^ 63)-1而且结果大于此值。
为了避免这个问题,在处理大量算术时,你应该总是使用BigInteger
。示例代码如下所示
BigInteger.valueOf(123L).multiply(BigInteger.valueOf(456L));
答案 3 :(得分:0)
关于行为,两个例子都是溢出。一个答案是否定的事实并没有增加任何特殊含义。你乘以的第一组数字恰好产生一个long,其最高位为1,而后者则不是。