誤差
桁落ち
値がほぼ等しい数値の減算によって有効桁数減少することを 桁落ち と呼びます。
以下のプログラムを実行してみましょう。
function printBits(v) {
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
view.setFloat32(0, v);
const bits = view.getUint32(0);
console.log(bits.toString(2).padStart(32, "0"), view.getFloat32(0));
}
const a = 12345.6;
const b = 12345.7;
printBits(a);
printBits(b);
printBits(a - b);
const c = 0.6;
printBits(c);
printBits(a - c);
実行結果は以下のようになります。
01000110010000001110011011001101 12345.7
01000110010000001110011001100110 12345.6
00111101110011001100110011001101 0.1000000000003638
00111111000110011001100110011010 0.6
01000110010000001110010001100110 12345.1
a - c では指数部の値が保たれているのに対して、a - b のときは指数部の値が小さくなり、有効桁数が減っていることが確認できます。
情報落ち
絶対値の大きい数値と小さい数値の加減算をした場合に生じる誤差を 情報落ち と呼びます。 情報落ちでは絶対値が小さい数値が正しく演算結果に反映されません。
以下のプログラムを実行してみましょう。
const a = 1e20;
const b = 1e10;
const c = 1e1;
console.log(`a + b = ${a + b}`);
console.log(`a + c = ${a + c}`);
実行結果は以下の通りになります。
a + b = 100000000010000000000
a + c = 100000000000000000000
a + c では絶対値の小さい c の値が加算に反映されていません。
丸め誤差
丸め誤差は、実数を有限の桁数(bit 数)で表す際に、表現可能な桁数を超えた部分を四捨五入や切り上げ切り捨てによって丸めたことによって生じる誤差です。
前述の通り、0.1 は丸め誤差を生じます。
打ち切り誤差
打ち切り誤差 は、無限級数のように表される数を有限回の繰り返しで打ち切ることにより生じる誤差です。 数値計算アルゴリズムの設計に大きく関わります。
オーバーフロー・アンダーフロー
演算結果が表現可能な数値の範囲を超えた場合に誤差が生じます。 数値の絶対値が表現可能な最大値を超えた場合に オーバーフロー、最小値を下回った場合に アンダーフロー と呼びます。