有効桁を越える掛け算の実装
作者: ameya さん実行数: 569
※ 本ライブラリは会員の方が作成した作品です。内容について当サイトは一切関知しません。
ここでは掛け算の結果を2つの変数に格納して倍の桁数を確保する一つの方法を示しています。これは説明のため10桁に設定していますが50桁でも同じ考え方でできます。
ソースコードはこんな感じです
見づらいのでprintの行は省いています。
/* ketaは桁数を表す予約語です */
ketahalf = keta / 2; /* ← 桁数の半分で分割用 */
mxall = 10 ^ keta; /* ← 上位の桁を表示するときに指数表示を */
mxhalf = 10 ^ ketahalf; /* ← 避けるために、これらで割っています。*/
/* 入力はAとBで、それぞれ ah,a と bh,b に分割します */
ah = rounddown(A, -ketahalf);
bh = rounddown(B, -ketahalf);
a = A - ah;
b = B - bh;
/* 半分に分けるのは掛け算で有効数字を桁数内に収めるためです */
/* 上位どうしと下位どうしの掛け算 */
cch = ah * bh;
cc = a * b;
/* たすき掛け */
m1 = ah * b;
m2 = bh * a;
/* たすき掛けの結果をそれぞれ分割 */
mh1 = rounddown(m1, -keta);
m1 = m1 - mh1;
mh2 = rounddown(m2, -keta);
m2 = m2 - mh2;
/* たすき掛け同士の足し算 */
th = mh1 + mh2;
/* ここで下位の足し算は繰り上がりの可能性があるのでテクニックを使っています */
tt = (m1 - 5E+9) + (m2 - 5E+9);
if (tt < 0) {
tt = tt + 1E+10;
} else {
th = th + 1E+10;
}
/* 最初の上位下位それぞれの掛け算と足しあわせます */
cch = cch + th;
/* ここも下位に繰り上がりの可能性があります */
cc = (cc - 5E+9) + (tt - 5E+9);
if (cc < 0) {
cc = cc + 1E+10;
} else {
cch = cch + 1E+10;
}
/* 答えを表示します。*/
println(-11, cch / mxall, cc);
/* なかなか理解しづらいと思いますが、
ここまで色々しているのはあくまで『有効数字の保存』である
という点に注意すると色々見えてくると思います。 */
見づらいのでprintの行は省いています。
/* ketaは桁数を表す予約語です */
ketahalf = keta / 2; /* ← 桁数の半分で分割用 */
mxall = 10 ^ keta; /* ← 上位の桁を表示するときに指数表示を */
mxhalf = 10 ^ ketahalf; /* ← 避けるために、これらで割っています。*/
/* 入力はAとBで、それぞれ ah,a と bh,b に分割します */
ah = rounddown(A, -ketahalf);
bh = rounddown(B, -ketahalf);
a = A - ah;
b = B - bh;
/* 半分に分けるのは掛け算で有効数字を桁数内に収めるためです */
/* 上位どうしと下位どうしの掛け算 */
cch = ah * bh;
cc = a * b;
/* たすき掛け */
m1 = ah * b;
m2 = bh * a;
/* たすき掛けの結果をそれぞれ分割 */
mh1 = rounddown(m1, -keta);
m1 = m1 - mh1;
mh2 = rounddown(m2, -keta);
m2 = m2 - mh2;
/* たすき掛け同士の足し算 */
th = mh1 + mh2;
/* ここで下位の足し算は繰り上がりの可能性があるのでテクニックを使っています */
tt = (m1 - 5E+9) + (m2 - 5E+9);
if (tt < 0) {
tt = tt + 1E+10;
} else {
th = th + 1E+10;
}
/* 最初の上位下位それぞれの掛け算と足しあわせます */
cch = cch + th;
/* ここも下位に繰り上がりの可能性があります */
cc = (cc - 5E+9) + (tt - 5E+9);
if (cc < 0) {
cc = cc + 1E+10;
} else {
cch = cch + 1E+10;
}
/* 答えを表示します。*/
println(-11, cch / mxall, cc);
/* なかなか理解しづらいと思いますが、
ここまで色々しているのはあくまで『有効数字の保存』である
という点に注意すると色々見えてくると思います。 */
この計算についてお客様の声はまだありません。
整数を考える場合、数値が有効桁で丸められてしまうのは問題ですよね。
本来、掛け算の答えを正確に出すには二倍の有効桁が必要です。