遠藤です。

> > ただ閾値を大きくとったのには理由があります。Karatsuba のアルゴリズムは
> > 中途半端な長さの bignum に対して、逆に遅くなるからです。
>
> そうなんですね.アルゴリズムの性質には詳しくなかったので勉強になります.

私も別に詳しいわけじゃないです (笑)


> どう見ても遠藤さんの実装のほうが平均すると高速であるように見えます.

いえ、平均するとむらたさんの方が早いです。

$ ruby -e '100.times { puts "puts((#{ rand(50000) }**#{
rand(50000)}).to_s(#{ rand(35) + 2 }))" }' > test_bignum.rb
$ time ./ruby.endoh test_bignum.rb > res.endoh.txt
real    2m53.565s
user    0m10.850s
sys     2m41.210s
$ time ./ruby.murata test_bignum.rb > res.murata.txt
real    2m32.398s
user    0m10.960s
sys     2m20.640s


特に一回目の to_s が著しく遅いので、何か下手をしている気がします。

$ ./ruby.endoh -e 't=Time.now; 3.times { (65536**65536).to_s;
t2=Time.now; p(t2-t); t=t2 }'
12.353483
8.567412
8.499522
$ ./ruby.murata -e 't=Time.now; 3.times { (65536**65536).to_s;
t2=Time.now; p(t2-t); t=t2 }'
8.295727
7.553404
9.150195


蛇足ですが、むらたさん版だと to_s(2) に失敗することがあるみたいです。

$ ./ruby.murata -e '(65536**65536).to_s(2)'
-e:1: warning: in a**b, b may be too big
-e:1: warning: Bignum out of Float range
-e:1:in `to_s': wrong number of arguments (1 for 0) (ArgumentError)
        from -e:1


> KARATSUBA_DIGITS を 1024, 512, 256, 128 と変化させて処理時間を計測しました.
(略)
> 以上の結果から,256桁と128桁の間で逆転していることが分かります.
> そこで提案ですが,KARATSUBA_DIGITS を 256 にして,big2str_table の
> エントリ数を 16 から 64 に増やすというのはどうでしょう?

なるほど、よさそうです。
1.8 用に移植もしてくださってありがとうございます。

-- 
Yusuke ENDOH <mame / tsg.ne.jp>