Java等效的无符号long long不是BigInteger?
我有一个简单的C代码,它使用无符号long-long:Java等效的无符号long long不是BigInteger?,java,c,long-integer,biginteger,Java,C,Long Integer,Biginteger,我有一个简单的C代码,它使用无符号long-long: #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, o
#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和C代码的输出不一样。
对于C代码,我得到10076018645131828514。而对于Java代码,我得到的是100702557336722946839210487799074
对于相同的输入,我无法理解这些不同的输出
PS:我在Ubuntu 32位机器上运行代码,使用gcc编译器
unsigned long
是一种有限长度的整数格式(可能)。这意味着它不能保存大于264-1的值
biginger
是任意长度的整数格式。这意味着存储在biginger
中的数字的大小实际上仅受可用内存的限制(以及一些JVM限制,如数组的大小,但这些限制非常大)
在C程序的计算中,无符号long-long
可能会溢出,您会得到一个截止结果
对于BigInteger
(它不会自动溢出),它只会给出准确的结果
您可以通过创建包含所需位掩码(64个设置位)的biginger
并使用myValue.and(mask)
获得“溢出”结果来模拟溢出
不过,你必须在可能发生溢出的每一步都这样做。而且它肯定比C代码慢。
long
s依赖于平台。你不能指望它们是便携式的,或者在其他机器上是相同大小的
尝试执行
sizeof(unsigned long-long)
以查看它在您的计算机上的实际大小。尽管我猜测您正在溢出。如果您执行实际乘法,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.
您有一个未签名的长环绕。:) 要正确计算答案,您需要一个至少能处理110位的类型。我怀疑在您的平台上,C
无符号long
可能只有64位,这是不够的。满溢了
Java程序的答案是正确的。这是一个广泛使用的线性同余生成器: (286293355577941757*N+3037000493)%2^64
模数部分由字大小以零成本提供,在本例中为64位,因此未包含在C代码中。使用多精度算法的任何版本的代码都是错误的,它必须是64位。状态的一个好数据类型是uint64\u t。C程序的答案太短了。在您的平台上,无符号long-long有多少位?不管它有多少,都不足以容纳答案。乘法
MULT*oldId
溢出。是~10^33。unsignedlong-long
decimal是什么意思?它在2**64-1
处溢出不是意味着它是二进制的吗?@svk:这是一个打字错误(或think-o):我实际上是指整数,我把它和bigdecime
混在一起了,它是bigteiger
的“表亲”,但与这个问题无关。是的,现在我明白了。在我的机器上,unsigned long long是64位
>>> 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.