在java中乘以大数

时间:2017-01-10 17:34:05

标签: java multiplication

我在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

4 个答案:

答案 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)

根据JLS 15.17.1

  

如果整数乘法溢出,则结果是数学乘积的低阶位,如某些足够大的二进制补码格式所示。因此,如果发生溢出,则结果的符号可能与两个操作数值的数学乘积的符号不同。

这就是您获得负值并且与输入数字没有任何关联的原因。这是因为Java中的long只能表示从-2 ^ 63到(2 ^ 63)-1而且结果大于此值。

为了避免这个问题,在处理大量算术时,你应该总是使用BigInteger。示例代码如下所示

BigInteger.valueOf(123L).multiply(BigInteger.valueOf(456L));

答案 3 :(得分:0)

关于行为,两个例子都是溢出。一个答案是否定的事实并没有增加任何特殊含义。你乘以的第一组数字恰好产生一个long,其最高位为1,而后者则不是。