toFixed の「丸め誤差」や「正しい対処法」を体験的に比較できるサンプルコードを紹介します。
CodePen やブラウザのコンソールでそのまま動かせます。
サンプル1:toFixed() の丸め誤差を観察する
<h2>toFixed() の丸め誤差を観察</h2>
<pre id="output"></pre>
<script>
const nums = [1.005, 0.615, 2.675, 10.235];
let result = "";
for (const n of nums) {
const fixed = n.toFixed(2);
result += `元の値: ${n}\n toFixed(2): ${fixed}\n\n`;
}
document.getElementById("output").textContent = result;
</script>
HTML🔍 解説
1.005や0.615は内部的に「少し小さい」数値(例:1.00499999…)になり、toFixed(2)では"1.00"や"0.61"になることがあります。- これが 浮動小数点誤差 の典型例です。
サンプル2:Number.EPSILON を使って補正した安全版丸め
<h2>Number.EPSILON を使った安全な丸め</h2>
<pre id="output2"></pre>
<script>
function safeRound(num, digits = 2) {
const factor = 10 ** digits;
return Math.round((num + Number.EPSILON) * factor) / factor;
}
const nums = [1.005, 0.615, 2.675, 10.235];
let result2 = "";
for (const n of nums) {
const fixed = n.toFixed(2);
const safe = safeRound(n, 2).toFixed(2);
result2 += `元の値: ${n}\n toFixed(2): ${fixed}\n safeRound: ${safe}\n\n`;
}
document.getElementById("output2").textContent = result2;
</script>
HTML🔍 ポイント
safeRound()は内部誤差を補うためにNumber.EPSILONを加算。- 多くのケースで
"1.01"のように人間が期待する四捨五入結果になります。
サンプル3:表示目的なら Intl.NumberFormat を使う
<h2>Intl.NumberFormat で丸めを制御(推奨:表示用)</h2>
<pre id="output3"></pre>
<script>
const formatter = new Intl.NumberFormat('ja-JP', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const nums = [1.005, 0.615, 2.675, 10.235];
let result3 = "";
for (const n of nums) {
const formatted = formatter.format(n);
result3 += `元の値: ${n}\n Intl.NumberFormat: ${formatted}\n\n`;
}
document.getElementById("output3").textContent = result3;
</script>
HTML🔍 ポイント
Intl.NumberFormatは国ごとのフォーマットや丸め規則を考慮。- 表示専用としては最も安定・信頼できる方法です。
サンプル4(おまけ):CodePen風 UI デモ
リアルタイムで入力して試したい方は下記の HTML を CodePen に貼り付けてみてください:
<h2>toFixed 丸め誤差デモ</h2>
<input type="number" id="num" value="1.005" step="0.001">
<input type="number" id="digits" value="2" min="0" max="10">
<button id="run">実行</button>
<pre id="out"></pre>
<script>
function safeRound(num, digits = 2) {
const factor = 10 ** digits;
return Math.round((num + Number.EPSILON) * factor) / factor;
}
document.getElementById("run").addEventListener("click", () => {
const n = parseFloat(document.getElementById("num").value);
const d = parseInt(document.getElementById("digits").value);
const toFixed = n.toFixed(d);
const safe = safeRound(n, d).toFixed(d);
const intl = new Intl.NumberFormat('ja-JP', {
minimumFractionDigits: d,
maximumFractionDigits: d
}).format(n);
document.getElementById("out").textContent =
`入力値: ${n}\n桁数: ${d}\n\n` +
`toFixed → ${toFixed}\n` +
`safeRound → ${safe}\n` +
`Intl.NumberFormat → ${intl}`;
});
</script>
HTMLこのデモでは:
- 数値と桁数を入力
toFixed/safeRound/Intl.NumberFormatの結果をリアルタイム比較
ができます。
See the Pen JavaScript toFixed Rounding Error Demo by MONO365 -Color your days- (@monoqlo365) on CodePen.
このデモでできること
| 機能 | 説明 |
|---|---|
| 🌙 ダークモード | ワンクリックでライト/ダーク切替 |
| 🧮 3種類の丸め比較 | toFixed, safeRound, Intl.NumberFormat の結果を同時表示 |
| 💾 履歴保存 | localStorage に直近10回分を保存/表示 |
| 📊 グラフ化 | Chart.js で結果の数値差をバーグラフ表示 |
| 🔁 履歴クリア | ワンクリックで削除可能 |
