JavaScriptでは小数点同士の四則演算などをする場合は誤差が発生します。
1 2 3 |
10.1 - 5.2 // 「4.8999999999999995」になる。 0.1 + 0.2 // 「0.30000000000000004」になる。 0.571*100 // 「57.099999999999994」になる。 |
原因
コンピュータ内部で発生する「丸め誤差」というものになります。
コンピュータ内部では小数点(浮動小数点)は2進数で計算していますが、人が扱うのは10進数になります。10進数→2進数にうまく変換できないことで発生します。
対処方法1:整数にしてから計算する。
これでもできます。ただ、小数点の桁数がわかっている場合しか対応できません。(ただ、ライブラリのインストールなどは不要な対処法になるので局所的な暫定的な対応とかではこれで問題ないかもしれません。)
1 2 3 |
aaa = 10.7; bbb = 9.1; ccc = ((aaa *10) - (bbb * 10)) / 10; // 1.6 |
上記のように10倍して整数にしてから計算してまた10で割っています。まあ冗長ですよね。
また、上記のケースではうまくいきますが小数第二位などを使った浮動小数などを扱う場合は小数計算などが入ってきてうまくいかない場合があるので確実ではないです。
対処方法2:ライブラリを使う。
丸め誤差対策のメジャーなライブラリは下記のようなものになります。
- BigDecimal.js
- bigNumber.js
- big.js
- decimal.js
big.js
- 6kbとサイズは小さい
- ES3でも動作するのでbabelなどでの変換は不要
bigNumber.js
- 8kbとサイズは小さい
1 2 3 |
const BigNumber = require('./bignumber.js'); const aaa = new BigNumber(0.2).minus(0.1); console.log(aaa.toString()); // 丸め誤差を起こさず0.1になる。 |
decimal.js
- typescriptに対応している。
- 複雑な数学的な計算を行う場合はこれを使う。
対処方法3:演算を他の言語で行う。
そもそも、小数点計算はバックエンド などの言語(例えば、JavaやSQLなど)に任せてフロントでは演算処理をしないという考え方ですね。
特に、金融系のアプリケーションとかであればなおさら精密なお金の金額の扱いが要求されるでしょうからこの選択肢を取ることがベストかもしれません。
この記事へのコメントはありません。