我有一个使用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编译器
答案 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)
以查看您的计算机实际有多大。虽然我的猜测是你正在溢出。