如何使用BigInteger类在Java中实现无符号的64位int?

时间:2009-04-20 08:50:41

标签: java types

我正在寻找一个精确容量为0到2 ^ 64的数据类型 - 1.我们知道Java本身不支持'unsigned'禁止char数据类型。

BigInteger类允许创建长数据类型不支持的更大数字。但我不确定BigInteger课程将如何满足我的目的。 BigInteger类只允许通过构造函数进行赋值。我看到以下可能性,但它会生成一个随机数。

BigInteger(int numBits, Random rnd) 
Constructs a randomly generated BigInteger, uniformly distributed over the range 0 to (2^numBits - 1), inclusive.

我看不到任何setValue(x)类型的API,它允许我为这个BigInteger选择我自己的值。如何使用BigInteger类实现这个或者还有其他方法吗?请发布代码示例。

PS:某人here发布的问题没有实施细节。

8 个答案:

答案 0 :(得分:6)

您经常可以使用Java的签名数字数据类型,就好像它们是未签名的一样。

请参阅此old answer有关Java中已签名与未签名的内容。

答案 1 :(得分:3)

为什么不编写自己的包装器并在下面使用签名长。如果用户希望以BigInteger的形式获取无符号值 - 测试符号并将2 ^ 64添加到BigInteger。

答案 2 :(得分:2)

您可能想要创建一个封装BigInteger的UInt64类;你还可以检查每个操作(add,mul等)是否返回一个无符号的64位BigInteger;模拟溢出可能很棘手

class UInt64 {

    private final BigInteger value;

    private UInt64(BigInteger aValue) {
         // method to enforce your class invariant: 0...2**64-1
         checkInvariantOf(aValue);
         value = aValue; 
    }

    public static UInt64 of(String value) {
         return new UInt64(new BigInteger(value));
    }

    public UInt64 add(UInt64 v) {
         return new UInt64(value.add(v.value));
    }

    ....
}

答案 3 :(得分:1)

正如你所发现的那样,

BigInteger是不可改变的。您可能希望查看子类化BigInteger,并编写自己的构造函数来验证输入,并在相关范围内发出正的BigInteger。

为了保持数字仅使用64位的要求,您可能还需要重载各种操作,因此它们会限制结果并返回新类的实例而不是新的BigInteger。

这可能是相当多的工作,但仍然要比从头开始做得好得多。

答案 4 :(得分:1)

您可以使用BigInteger.valueOf(l)从long创建BigInteger,其中l是long。

但是如果你想使用精确的64位,我会使用很长的时间。

答案 5 :(得分:1)

您可以将值0到2 ^ 64-1存储为长值。

许多操作按预期工作,但是大多数API和一些操作仅在它们采用签名操作时起作用,但是有解决方法。

然而,使用BigInteger可能更容易让人头疼。 ;)

答案 6 :(得分:1)

在Java SE 8及更高版本中,您可以使用长数据类型来表示无符号的64位长,其最小值为0,最大值为2 ^ 64-1。

答案 7 :(得分:1)

要将uint64输入到BigInteger中,可以使用带有字节数组和符号的构造函数:

public static BigInteger bigIntegerFromUInt64(long uint64) {
  if (uint64 < 0) {
    ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
    buffer.putLong(uint64);
    byte[] uint64Bytes = buffer.array();

    return new BigInteger(/* signum */ 1, uint64Bytes);
  } else {
    return BigInteger.valueOf(uint64);
  }
}