如何将最大的n位无符号整数分配给Java中的BigInteger

时间:2010-08-16 05:04:02

标签: java biginteger

我有一个使用大整数(例如160位)的方案,并且我正在尝试创建可能在运行时用n位数表示的最大可能无符号整数。在程序开始执行并从配置文件中读取值之前,不知道n的确切值。例如,n可能是160,或128,或192,等等......

最初我的想法是:

BigInteger.valueOf((long)Math.pow(2, n));

然后我意识到,转换为long会发生这种情况有点失败的目的,因为long在第一时间不包含足够的位来存储结果。有什么建议吗?

4 个答案:

答案 0 :(得分:9)

在最大的n位无符号数

让我们先看看这个数字是什么,数学上。

在无符号二进制表示中,最大的 n 位数将所有位设置为1.让我们看一些例子:

  

1 (2) = 1 = 2 1 - 1
  11 (2) = 3 = 2 2 - 1
  111 (2) = 7 = 2 3 - 1
  :
  1………1 (2) = 2 n -1
   名词

请注意,这也类似于十进制。最大的3位数字是:

  

10 3 - 1 = 1000 - 1 = 999

因此,找到最大 n 位无符号数的子问题是计算2 n


关于计算能力2

由于以下模式,现代数字计算机可以有效地计算两个幂:

  

2 0 = 1 <子>(2)
  2 1 = 10 <子>(2)
  2 2 = 100 <子>(2)
  2 3 = 1000 <子>(2)
  :
  2 名词 = 10………0 <子>(2)
   名词

也就是说,2 n 只是将其位 n 设置为1的数字,其他所有设置为0(请记住位编号使用从零开始的索引编译。)


解决方案

综上所述,我们使用BigInteger为我们的问题找到了这个简单的解决方案:

final int N = 5;
BigInteger twoToN   = BigInteger.ZERO.setBit(N);
BigInteger maxNbits = twoToN.subtract(BigInteger.ONE);

System.out.println(maxNbits); // 31

如果我们使用long代替,那么我们可以这样写:

// for 64-bit signed long version, N < 64
System.out.println(
    (1L << N) - 1
); // 31

没有为long定义“设置位 n ”操作,因此传统上使用位移。实际上,这种移位技术的BigInteger模拟也是可能的:

System.out.println(
    BigInteger.ONE.shiftLeft(N).subtract(BigInteger.ONE)
); // 31

另见


其他BigInteger提示

BigInteger确实有pow方法来计算任意数字的非负幂。如果您使用模块化环,还有modPowmodInverse

您可以单独setBitflipBittestBit。您可以获得整体bitCount,按位and执行另一个BigIntegershiftLeft / shiftRight等。

作为奖励,您还可以计算gcd或检查数字isProbablePrime

始终请记住,BigIntegerString一样,不可变。您无法在实例上调用方法,并期望修改该实例。相反,始终将方法返回的结果分配给变量。

答案 1 :(得分:3)

只是为了澄清你想要最大 n位数(即,所有n位都设置)。如果是这样,以下内容将为您完成:

BigInteger largestNBitInteger = BigInteger.ZERO.setBit(n).subtract(BigInteger.ONE);

在数学上等效于2 ^ n - 1.您的问题是如何做2 ^ n实际上是最小的n + 1位数。你当然可以这样做:

BigInteger smallestNPlusOneBitInteger = BigInteger.ZERO.setBit(n);

答案 2 :(得分:2)

我认为BigInteger中直接有 pow 方法。您可以将它用于您的目的

答案 3 :(得分:0)

我能想到的最快捷的方法是使用BigInteger的{​​{1}}构造函数。

byte[]从字节数组构造BigInteger(byte[] val)对象。但是,您正在处理位,因此为表示2 ^ 40 - 1的39位整数创建一个可能包含{127,255,255,255,255}的byte []可能有点乏味。

您还可以使用构造函数BigInteger - 如果您不介意解析字符串的性能问题,那么您的代码中可能更容易发生什么。然后你可以生成一个像BigInteger(String val, int radix)这样的字符串然后调用val = "111111111111111111111111111111111111111" - 产生相同的39位整数。

第一个选项需要考虑如何表示您的号码。那个特定的构造函数需要一个二进制 - 赞美,big-endian表示的数字。第二个可能稍微慢一些,但更清晰。

编辑:更正的数字。我以为你的意思是代表2 ^ n,并没有正确读取n位可以存储的最大值。