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