Java 新的BigInteger(字符串)性能/复杂性

Java 新的BigInteger(字符串)性能/复杂性,java,performance,complexity-theory,biginteger,Java,Performance,Complexity Theory,Biginteger,我想知道使用新的biginger(String)构造函数构建biginger对象的性能/复杂性 考虑以下方法: public static void testBigIntegerConstruction() { for (int exp = 1; exp < 10; exp++) { StringBuffer bigNumber = new StringBuffer((int) Math.pow(10.0, exp)); for (int i

我想知道使用
新的biginger(String)
构造函数构建biginger对象的性能/复杂性

考虑以下方法:

  public static void testBigIntegerConstruction()
  {
    for (int exp = 1; exp < 10; exp++)
    {
      StringBuffer bigNumber = new StringBuffer((int) Math.pow(10.0, exp));
      for (int i = 0; i < Math.pow(10.0, exp - 1); i++)
      {
        bigNumber.append("1234567890");
      }

      String val = bigNumber.toString();
      long time = System.currentTimeMillis();
      BigInteger bigOne = new BigInteger(val);
      System.out.println("time for constructing a 10^" + exp
          + " digits BigInteger : " + ((System.currentTimeMillis() - time))
          + " ms");
    }
  }
忽略10^5以内的行(由于(处理器)缓存效果、JIT编译等可能引入的失真),我们可以清楚地看到O(n^2)的复杂性。 请记住,
BigInteger
上的每一个操作都会由于不变性而创建一个新的操作,这是对大量数据的主要性能惩罚

问题:

  • 我错过什么了吗

  • 为什么会这样

  • 这在最近的JDK中是否已修复

  • 还有其他选择吗

更新:

我做了进一步的测量,我可以从一些答案中证实这一说法:
似乎
BigInteger
是为后续的数值运算而优化的,其代价是巨大数字的更高构建成本,这对我来说似乎是合理的。

从某种程度上说,这是因为“传统”字符串解析循环

for each digit y from left to right:
  x = 10 * x + y
您有这样一个问题:
10*x
不可避免地会在
x
的长度上花费线性时间,并且该长度对于每个数字或多或少都会增长,这也是不可避免的

(实际的实现比这要聪明一些——它试图一次解析一个
int
值的二进制数字,因此循环中的实际乘法器更有可能是10亿或20亿——但是的,它总体上仍然是二次的。)

也就是说,一个带有
10^6
位的数字至少是一个googol,这比我听说的任何用于加密目的的数字都要大。你正在解析一个占用2兆内存的字符串。是的,这需要一段时间,但我怀疑JDK的作者没有看到为这种罕见的用例进行优化的意义。

如果将
biginger
指定为十进制数字,则十进制到二进制转换会导致O(n^2)作用力


此外,10^7位数字是一个非常庞大的数字。对于RSA这样的典型加密算法,您需要处理10^3到10^4位数字。大多数
biginger
操作都没有针对如此大量的数字进行优化。

您实际上是在测量解析字符串和创建biginger所需的时间解决大整数的效率要比这高很多。

从源代码看似乎是合理的…您是否使用了非字符串构造函数进行了测量,我不确定操作是否会序列化为字符串。也就是说,您的数字长度为
10^(10^7)
for each digit y from left to right:
  x = 10 * x + y