10 進固定小数点数
シミュレーションやコンピュータグラフィックスでは、その目的に応じてある程度の誤差は許容することができます。 一方で、例えば金銭を扱うシステムでは誤差が生じると困ります。 これまでみてきたように、浮動小数点数では 0.1 という極めて身近な小数でも誤差を生じました。
以下は 1.0 - 0.9 を計算するプログラムです。
const a = 1.0;
const b = 0.9;
console.log(`a - b = ${a - b}`);
実行結果は以下のように誤差を生じます。
a - b = 0.09999999999999998
コンピュータで、誤差が出ないように小数を扱うことはできるのでしょうか?
コンピュータのプロセッサが採用している浮動小数点数を使うのではなく、10 進数の実数の計算の仕組みをプログラム上で実現することでそれは可能です。
JavaScript では、decimal.js 等の外部ライブラリによって 10 進固定小数点数を表す Decimal
クラスを利用できます。
BigDecimal
を用いた 1.0 - 0.9 の計算は以下のようになります。
const a = new Decimal("1");
const b = new Decimal("0.9");
console.log(`a - b = ${a.minus(b)}`);
実行結果は以下のようになります。
a - b = 0.1
誤差のない計算結果 0.1 を得ることができました。
一方で、Decimal にもメリット・デメリットがあります。
Number
に対する Decimal
のメリットは以下の通りです。
- 浮動小数点数に由来する演算誤差が生じない
- 桁数に制限がない
一方で以下のデメリットがあります。
- 演算が低速
- JavaScript においては組み込みの演算子が使用できず、演算のためのメソッドを使う必要がある