Java相当于unsigned long long不是BigInteger?

时间:2013-11-13 09:13:49

标签: java c long-integer biginteger

我有一个使用unsigned long long的简单C代码:

#include<stdlib.h>
unsigned long long get_random_id(const char *imeiId)
{
    const unsigned long long MULT = 2862933555777941757LL;
    const unsigned long long ADDEND = 3037000493LL;
    unsigned long long newId, oldId;
    oldId = atoll(imeiId);
    newId = MULT * oldId + ADDEND;
    return newId;
}
void main()
{
  printf("%llu",get_random_id("351746051295833"));
}

我应该把它转换为java代码,所以我使用BigInteger如下:

public static void main(String args[]) {
        System.out.println(get_random_id("351746051295833"));
    }
    static BigInteger get_random_id(String imeiId) {
        final String MULT_STRING = "2862933555777941757";
        final String ADDEND_STRING = "3037000493";

        BigInteger MULT =  new BigInteger(MULT_STRING);
        BigInteger ADDEND = new BigInteger(ADDEND_STRING);
        BigInteger oldId = new BigInteger(imeiId);
        BigInteger temp = MULT.multiply(oldId);
        BigInteger newId = temp.add(ADDEND);
        return newId;
    }

我的问题是我没有得到相同的Java和C代码输出。 对于C代码,我得到10076018645131828514.而对于Java代码,我得到1007025573367229468539210487799074。

我无法理解同一输入的这些不同输出。

PS:我在Ubuntu 32位机器上运行代码并使用gcc编译器

5 个答案:

答案 0 :(得分:3)

unsigned long long是一种有限长度的整数格式(可能是64bit or more)。这意味着它不能保持大于2 64 -1的值。

BigInteger是任意长度的整数格式。这意味着存储在BigInteger中的数字的大小实际上仅受可用内存的限制(以及一些JVM限制,例如数组的大小,但这些限制非常大)。

在C程序的计算中,unsigned long long可能会溢出,并且会得到截止结果。

BigInteger不会发生这种情况(它永远不会无声地溢出),它只会给出确切的结果。

您可以通过创建保存所需位掩码(64位设置)的BigInteger并使用myValue.and(MASK)来获得“溢出”结果来模拟溢出。

尽管如此,你必须在可能发生溢出的每一步都这样做。它肯定比C代码慢。

答案 1 :(得分:1)

如果你进行实际的乘法,那么Java的输出是正确的。

我使用Python查找以下内容:

>>> 2862933555777941757 * 351746051295833 + 3037000493
1007025573367229468539210487799074L

然后获取您在C代码中获得的内容:

>>> 2862933555777941757 * 351746051295833 + 3037000493
1007025573367229468539210487799074L
>>> _ % (2**64)   # Previous result mod 2 ^ 64 (**Assumming ULL is 64 bits on your system**)
10076018645131828514L  # This is what you have as the output of your C code.

你有一个unsigned long long wrap。 :)

答案 2 :(得分:1)

您需要一种能够处理至少110位的类型,才能正确计算答案。我怀疑在你的平台上,C unsigned long long可能只有64位,这还不够。它正在溢出。

Java程序的答案是正确的。

答案 3 :(得分:1)

这是一种广泛使用的线性同余生成器:

(2862933555777941757 * N + 3037000493)%2 ^ 64

模数部分由字大小以零成本提供,在这种情况下为64位,因此未包括在C代码中。使用多精度算术的任何版本的代码都是错误的,它必须是64位。状态的良好数据类型是uint64_t。

答案 4 :(得分:0)

long long与平台有关。您不能指望它们是便携式的,或者在其他机器上具有相同的尺寸。

尝试执行sizeof(unsigned long long)以查看您的计算机实际有多大。虽然我的猜测是你正在溢出。