简体   繁体   English

Java 等价于 unsigned long long 是不是 BigInteger?

[英]Java equivalent of unsigned long long is not BigInteger?

I have a simple C code which uses unsigned long long:我有一个使用 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"));
}

I'm supposed to convert this to a java code, so I'm using BigInteger as follows:我应该将其转换为 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;
    }

My problem here is that I'm not getting the same output for Java and C Code.我的问题是我没有得到相同的 Java 和 C 代码输出。 For C code, I'm getting 10076018645131828514. while for Java code I'm getting 1007025573367229468539210487799074.对于 C 代码,我得到 10076018645131828514。而对于 Java 代码,我得到 1007025573367229468539210487799074。

I'm not able to understand these different outputs for the same input.对于相同的输入,我无法理解这些不同的输出。

PS: I'm running the code on Ubuntu 32 bit machine and using gcc compiler PS:我在 Ubuntu 32 位机器上运行代码并使用 gcc 编译器

unsigned long long is a limited-length integer format (probably 64bit or more ). unsigned long long是一种长度有限的整数格式(可能是64 位或更多)。 That means that it can hold no value larger than 2 64 -1.这意味着它不能保存大于 2 64 -1 的值。

A BigInteger is an arbitrary-length integer format. BigInteger是一种任意长度的整数格式。 That means that the size of the number stored in a BigInteger is effectively limited only by the available memory (and some JVM restrictions like the size of an array, but those are pretty big).这意味着存储在BigInteger中的数字的大小实际上仅受可用内存的限制(以及一些 JVM 限制,例如数组的大小,但这些限制非常大)。

Somewhere in your calculation in the C program the unsigned long long probably overflows and you get a cut-off result.在 C 程序计算中的某个地方, unsigned long long可能会溢出,您会得到一个截止结果。

That doesn't happen with BigInteger (it never silently overflows), it will just give the exact result. BigInteger不会发生这种情况(它永远不会默默地溢出),它只会给出确切的结果。

You can emulate an overflow by creating a BigInteger that holds the desired bit mask (64 set bits) and using myValue.and(MASK) to get the "overflown" result.您可以通过创建一个包含所需位掩码(64 个设置位)的BigInteger并使用myValue.and(MASK)来模拟溢出,以获得“溢出”结果。

You'd have to do that at every step where an overflow could occur, 'though.但是,您必须在可能发生溢出的每一步都这样做。 And it would certainly be slower than the C code.它肯定会比 C 代码慢。

Output of Java is correct, if you do the actual multiplication.如果您进行实际的乘法运算,Java 的输出是正确的。

I used Python to find the below:我使用 Python 找到以下内容:

>>> 2862933555777941757 * 351746051295833 + 3037000493
1007025573367229468539210487799074L

Then to get what you are getting in your C code:然后得到你在你的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.

You have an unsigned long long wrap around.你有一个无符号长长的环绕。 :) :)

You'll need a type that can handle at least 110 bits, to calculate the answer correctly.您需要一种可以处理至少 110 位的类型,才能正确计算答案。 I suspect that on your platform, a C unsigned long long is probably only 64 bits, which is not enough.我怀疑在您的平台上,C unsigned long long可能只有 64 位,这还不够。 It's overflowing.溢出来了

The answer from your Java program is correct.您的 Java 程序的答案是正确的。

This is a widely used linear congruential generator:这是一个广泛使用的线性同余生成器:

(2862933555777941757 * N + 3037000493) % 2^64 (2862933555777941757 * N + 3037000493) % 2^64

The modulus part is provided at zero cost by the word size, in this case 64 bits, and therefore has not been included in the C code.模数部分由字长以零成本提供,在本例中为 64 位,因此未包含在 C 代码中。 Any version of this code using multi-precision arithmetic is wrong, it must be 64-bits.使用多精度算术的任何版本的代码都是错误的,它必须是 64 位的。 A good data type for the state would be uint64_t.一个好的状态数据类型是 uint64_t。

long long s are platform dependent. long long是平台相关的。 You can't count on them being portable, or being the same size on other machines.你不能指望它们是便携的,或者在其他机器上尺寸相同。

Try doing a sizeof(unsigned long long) to see how big it actually is on your machine.尝试执行sizeof(unsigned long long)以查看它在您的机器上的实际大小。 Although my guess is that you're getting overflow.虽然我的猜测是你正在溢出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM