1億桁×1億桁の開発状況報告2
前はkaratsuba法の名前が出てくるところまで話が進んだんですよね?
前も言いましたがlognint.dllとは、ものすごいながい桁数の数値も計算できるようにするためのプラグインです。
これを使います。
HSPユーザーでこれを使ってる人はなかなか見ないもんで、その技術解説をしているホームページなども見ないので、このブログがHSPユーザーとして一番最初に詳しくlognintについて技術解説することになりそうです!!
なんかうれしい!!
もともと私は四則演算とか(自称)とても得意なんで、一般の人には負けないつもりです!
さてkaratsuba法のプログラムについてですが
ちょっとプログラム的な話ではなく、ほんと数学的な話になりそうですが、まぁ仕方ないですが、許してください
karatsuba法は一言で言うと、とても長い桁数を演算するときに使え、計算手順を効率よくすることで計算時間を短くするという方法の一つです。
実はもっと効率のいい高速フーリエ変換という方法もあるのですが、自分の技術不足でkaratsubaが限界です・・・・
さて実際の手順ですが、
まず四則演算の計算で一番時間がかかるのが掛け算、割り算。
桁数に比例して時間が伸びます。
足し算引き算は、掛け算と比べほとんどゴミのようなものです。
なので、効率化するべきは掛け算です。(割り算は置いておく)
ここでちょっと分かりやすく、10桁×10桁の掛け算を考えます。
本当は千桁くらいから使わないと意味がないのですが
例えば1384501239×5678221098の計算
このとき、普通
a=1384501239
b=5678221098
c=a*b
とこうやりますね?
ここで、桁数を最大5桁に制限し変数を分割することを考えます。
a1=13845
a2=1239
b1=56782
b2=21098
とし
c=a1*b1*10^10+(a1*b2+a2*b1)*10^5+a2*b2
とこうするとします。
ここで*10^10と*10^5は、変数上でも後ろに0がつくだけなので計算時間がまったくかからないものとします
一つ一つの掛け算が5桁×5桁になったので、10桁にときと比べると4分の1になったにですが、これでも、掛け算が合計4つになり、結局計算時間的にはなにも変わりません。
ここでやっとkaratsuba法の登場
括弧でくくりまくって
c=(a1*b1)*10^10+(a2*b2)-((a1-a2)*(b1-b2)+(a1*b1)+(a2*b2))*10^5
とこうします。
一見掛け算が増えたように見えますが、a1*b1とa2*b2のところが2箇所ずつあります
だからそこの計算はしなくていいのです。
簡潔に書くと
c1=a1*b1
c2=a2*b2
c=c1*10^10-((a1-a2)*(b1-b2)+c1+c2)*10^5+c2
とこうなります!
よく見てみると*10^10とか省くと、掛け算が3回に減っています!
これが計算の効率化です。
さっきまでずっと、*10^10をの計算時間を省くのを気にしている人がいるかもしれません
が、実際の計算で、計算結果を一つの変数にまとめなければいけないというルールはありません。
1億桁の計算結果を出力するプログラムでは、1万桁ずつ1万個の変数に区切って出力する方法をとっても
なんら問題はおきないのです(当然繰り上がり処理は別途必要になります)
だから、「この変数は10^10が本来かかっている数」として自分の中で考えておけば、わざわざコンピューターに
*10^10の計算をやらせる必要はなくなるのです。
このようにして掛け算が効率化されました。
次のハードルは、karatsuba法の帰納的活用法です。
4回から3回に減った掛け算の中でさらにまたkaratsuba法を適応して計算時間を4分の3に減らします