JavaScriptで「0.1+0.2≠0.3」の浮動小数点を扱うための解説と対処法

JavaScriptの「0.1+0.2≠0.3」について

以前、浮動小数点の計算に関する以下の記事が話題になっていた。

"「0.1+0.2≠0.3」だから浮動小数点数を扱うときには気を付けましょう" はいいんだけど結局どうしたらいいのかまでフォローしたほうが親切だと思ったので調べてみた

なろう小説のタイトルかな?😅

で、この記事の中でJavaScriptの場合は以下の関数を作成すれば「0.1 + 0.2」の結果を「0.3」か判定できると書かれていました。

function floatEquals(a, b, epsilon = 0.00001) {
    return Math.abs(a - b) < epsilon;
}

let a = 0.1;
let b = 0.2;

if (floatEquals(a + b, 0.3)) {
    console.log("等しい");
} else {
    console.log("等しくない");
}

「0.1 + 0.2」の結果を出す関数

前述のコードは計算した結果が「0.3」と等しいかどうかの判定はできますが、「0.1 + 0.2」の結果は出せません。

「0.1 + 0.2 = 0.3」などの小数点の結果を出すには、以下のような関数を作成して計算します。

小数点の足し算用の関数

function addDecimals(a, b, decimal = 10) {
  const factor = 10 ** decimal
  return (a * factor + b * factor) / factor
}
console.log(addDecimals(0.1, 0.2)) // 0.3

コード内のdecimalの変数は計算の際に使用する精度(小数点以下の桁数)を指定するためのものです。

例えばaddDecimalsは10の10乗を小数点にかけることで、一度整数にしたあと、同じ変数で割って小数点に戻しています。

こうすることで「0.1 + 0.2 = 0.3」になるようにしています。

JavaScriptでは小数点で桁が10桁以上の計算が行われることは少ないので、ほとんどの方法はこの関数で対処できるでしょう。

足し算以外の引き算、掛け算、割り算の四則演算の場合は以下のとおりです。

小数点の引き算用の関数

function subtractDecimals(a, b, decimal = 10) {
  const factor = 10 ** decimal
  return (a * factor - b * factor) / factor
}
console.log(subtractDecimals(0.3, 0.2)) // 0.1

小数点の掛け算用の関数

function multiplyAndRound(a, b, decimal = 10) {
  return Number((a * b).toFixed(decimal))
}
console.log(multiplyAndRound(0.1, 0.1)) // 0.01

小数点の割り算用の関数

function divisionAndRound(a, b, decimal = 10) {
  return Number((a / b).toFixed(decimal))
}
console.log(divisionAndRound(0.3, 0.1)) // 3

JavaScriptライブラリを使用する方法

JavaScriptライブラリを使用する場合は、よく使用されているbignumber.jsを使用すると良いでしょう。

bignumber.js

JavaScriptライブラリを使用するとJavaScriptのファイルサイズが関数を自作するのに比べてかなり大きくなります。

そのため、必要性がなければ使用は避けたほうが良いでしょう。