大部分计算(如果不是全部)都是将当前 bigint 加倍的部分
如果您所有的计算都在将数字加倍,那么您为什么不保留一个不同的(以 2 为底)比例字段?然后只需添加一个比例,它可以只是一个普通的旧 int。这肯定会比任何几百万位的操作都要快。
IOW,使用大浮点数。
随机基准
use Math::GMP;
use Time::HiRes qw(clock_gettime CLOCK_REALTIME CLOCK_PROCESS_CPUTIME_ID);
my $n = Math::GMP->new(2);
$n = $n ** 1_000_000;
my $m = Math::GMP->new(2);
$m = $m ** 10_000;
my $str;
for ($bits = 1_000_000; $bits <= 2_000_000; $bits += 10_000) {
my $start = clock_gettime(CLOCK_PROCESS_CPUTIME_ID);
$str = "$n" for (1..3);
my $stop = clock_gettime(CLOCK_PROCESS_CPUTIME_ID);
print "$bits,@{[($stop-$start)/3]}\n";
$n = $n * $m;
}
似乎表明 GMP 以某种方式在 O(n) 时间内进行转换(其中 n 是二进制数中的位数)。这可能是由于 1 后面跟着一百万(或两个)零的特殊情况;GNU MP 文档说它应该更慢(但仍然比 O(N^2) 好。
http://img197.imageshack.us/img197/6527/chartp.png