【入門編】 浮動小数点数の精度問題と誤差 – JavaScript実践ガイド

こんにちは!フロントエンドの世界へようこそ。
JavaScriptを触り始めて、「あれ、これっておかしくない?」と、計算結果を見て首をかしげたことはありませんか?

そう、あの有名な「0.1 + 0.2 は 0.3 にならない」問題です。

初めてこれを見たとき、多くの人が「JavaScriptが壊れているの!?」と焦ります。でも、安心してください。これは壊れているわけではなく、コンピュータが「数字を扱うときの宿命」を背負っているからなんです。

今日は、なぜこんな不思議なことが起きるのか、そして現場でどう付き合っていけばいいのかを、一緒に紐解いていきましょう。

—

コンピュータは「分数」が苦手?

まず、身近な例え話をしましょう。
あなたは今、ケーキを3等分に切り分けようとしています。完璧に同じサイズに切れますか?……いや、現実にはどんなに頑張っても、原子レベルで言えばわずかなズレが生じますよね。

実は、コンピュータもこれと同じような苦労をしています。

コンピュータは、すべての数字を「0」と「1」の組み合わせだけで表現します。これを「二進数」と呼びます。
私たちが普段使う「十進数」だと、「0.1」はシンプルですが、これを二進数に直すと……実は「0.0001100110011……」と、無限に続く割り切れない数字になってしまうんです。

コンピュータにもメモリ(記憶できる容量)の限界があるので、無限に続く数字をどこかで切り捨てて保存します。その「わずかな切り捨て」が積み重なった結果、0.1と0.2を足すと、ほんの少しだけ誤差が出てしまう……というのが、この現象の正体です。

—

実際に確認してみよう

百聞は一見にしかず。まずはブラウザのコンソールを開いて、これを確認してみましょう。

// 0.1と0.2を足してみる
const result = 0.1 + 0.2;

console.log(result);
// 表示結果: 0.30000000000000004
// 「0.00000000000000004」という小さな誤差が紛れ込んでいます!

// だから、0.3と比較すると……
console.log(result === 0.3);
// 表示結果: false
// コンピュータは「0.30000000000000004 は 0.3 とは違うよ!」と判断します

ね? JavaScriptが嘘をついているわけではなく、コンピュータが「一生懸命計算した結果、どうしてもここまでしか正確に表せなかったんだ」と正直に答えているだけなんです。

—

実務でどう回避すればいいの?

「じゃあ、ECサイトでお金の計算をするときはどうするの?」と心配になりますよね。大丈夫、プロの現場ではちゃんと対策があります。

1. 整数に直して計算する(一番おすすめ!)

一番シンプルで確実な方法は、「小数点を使わない」ことです。
例えば、100円の計算をするなら、100.00円ではなく「10000銭」として扱います。

// 0.1 + 0.2 を計算したいとき
// 10倍して整数にしてから足して、あとで10で割る
const safeResult = (0.1 10 + 0.2 10) / 10;

console.log(safeResult); // 0.3
console.log(safeResult === 0.3); // true

2. 「ごくわずかな差」なら無視する

もし科学的な計算や厳密な精度が求められない場合(例えばUI上の位置調整など)は、誤差を許容する書き方をします。

// 誤差の範囲(イプシロンといいます)を決めて、その範囲内ならOKとする
const diff = Math.abs((0.1 + 0.2) – 0.3);

// 誤差がとても小さければ(Number.EPSILON未満なら)同じとみなす
if (diff < Number.EPSILON) { console.log("実質0.3です!"); } ---

最後に:つまずくのは「学んでいる証拠」です

この「浮動小数点数の誤差」に気づいたあなたは、すでに立派な開発者の視点を持っています。多くの人が「とりあえず動くからいいや」と通り過ぎてしまうところを、あなたは「なぜ?」と立ち止まって考えた。その姿勢こそが、これから素晴らしいエンジニアになっていくための大切な一歩です。

JavaScriptはとても柔軟で、ときにこんな「お茶目なクセ」を見せますが、そこを理解して付き合えるようになると、ますますプログラミングが楽しくなりますよ。

これからも、焦らず、楽しみながら一緒にコードを書いていきましょうね!応援しています!

コメント

タイトルとURLをコピーしました