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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/767456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:15:14  来源:igfitidea点击:

How to implement an unsigned 64-bit int in Java using BigInteger class?

javatypes

提问by Real Red.

I am looking for one datatype with exact capacity of 0 to 2^64 - 1. We know that Java as it is does not support 'unsigned' barring char datatype.

我正在寻找一种精确容量为 0 到 2^64 - 1 的数据类型。我们知道 Java 不支持“无符号”禁止字符数据类型。

There is BigInteger class that allows creation of larger numbers that long datatype cannot support. But I am not sure how BigInteger class would serve my purpose. BigInteger class allows assignment through constructors only. I see the following possibility but it generates a random number.

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

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

I can't see any setValue(x) kind of API that'd let me choose my own value to this BigInteger. How to implement this using BigInteger class or is there any other way of doing it? Please post code sample.

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

PS: The question posted by someone heredoes not have implementation details.

PS:这里有人发布的问题没有实现细节。

回答by unwind

BigIntegers are immutable, just as you've found. You might want to look into subclassing BigInteger, and writing your own constructor that validates input, and emits a positive BigInteger in the relevant range.

正如您发现的那样,BigInteger是不可变的。您可能想要研究 BigInteger 的子类化,并编写自己的构造函数来验证输入,并在相关范围内发出一个正 BigInteger。

To maintain the requirement that numbers are only using 64 bits, you might need to overload the various operations too, so they limit the result and return an instance of your new class rather than a new BigInteger.

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

This is probably quite a bit of work, but should still be far better than doing it all from scratch.

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

回答by Ingo

You can create a BigInteger from a long with BigInteger.valueOf(l), where l is a long.

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

But if you want to work with exact 64-bits, I'd use just long.

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

回答by mP.

Why not write your own wrapper and underneath use a signed long. If the user wishes to fetch the unsigned value as a BigInteger - test the sign and add 2^64 to the BigInteger.

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

回答by dfa

you may be want to create a UInt64 class, that encapsulate a BigInteger; you can also check that every operation (add, mul, etc) returns an unsigned 64 bit BigInteger; simulating the overflow maybe tricky

你可能想要创建一个 UInt64 类,封装一个 BigInteger;您还可以检查每个操作(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));
    }

    ....
}

回答by starblue

You can often use Java's signed numeric data types as if they were unsigned.

您通常可以像使用无符号一样使用 Java 的有符号数字数据类型。

See this old answerabout signed vs. unsigned in Java.

请参阅有关 Java 中签名与未签名的旧答案

回答by Peter Lawrey

You can store values 0 to 2^64-1 in a long value.

您可以将 0 到 2^64-1 的值存储在 long 值中。

Many operations work as expected however most of the APIs and some of the operations only work as they assume signed operations however there are workarounds.

许多操作按预期工作,但是大多数 API 和一些操作仅在假设签名操作时才有效,但有解决方法。

Using BigInteger may be simpler to get your head around however. ;)

然而,使用 BigInteger 可能更容易理解。;)

回答by crownus

In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 2^64-1.

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

回答by weston

To input a uint64 into a BigInteger, you can use a constructor that takes a byte array and a signum:

要将 uint64 输入到 a 中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);
  }
}