【问题标题】:How to implement an unsigned 64-bit int in Java using BigInteger class?如何使用 BigInteger 类在 Java 中实现无符号 64 位 int?
【发布时间】:2010-10-20 12:40:33
【问题描述】:

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

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发的问题没有实现细节。

【问题讨论】:

  • 您能否明确说明您需要该数据类型的确切原因以及您想用它做什么?可能有一些方法可以简化问题...
  • C++ 支持这样的数据类型。我正在与 C++ 交互,并认为在 Java 端也有类似的数据类型会更好,而不是必须在 C++ 端操作数据并进行转换。
  • 对于另一种方法,请在此处查看我的答案:stackoverflow.com/questions/508630/…

标签: java types


【解决方案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);
  }
}

【讨论】:

    【解决方案2】:

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

    【讨论】:

    【解决方案3】:

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

    请参阅old answer,了解 Java 中的已签名与未签名。

    【讨论】:

      【解决方案4】:

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

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

      不过,使用 BigInteger 可能更容易理解。 ;)

      【讨论】:

      • long 支持 -2^63 到 (2^63)-1,因为第一位是符号位。我想要 unsigned long ,其范围为 0 到 (2^64)-1。我想要的不是 2^(64-1)。它是 (2^64)-1。
      • 我相信区别取决于你。如果你使用+、-、^、&、|、>>、~你会发现结果是无法区分的。如果您调用 Long.toHexString(long) 它不会打印负数。
      【解决方案5】:

      您可能想要创建一个封装 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));
          }
      
          ....
      }
      

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

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

          但如果您想使用精确的 64 位,我会使用 long。

          【讨论】:

            【解决方案8】:

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

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

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

            【讨论】:

              猜你喜欢
              • 2023-03-11
              • 1970-01-01
              • 2015-12-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多