どの言語で起きるか
シルギアのツールは JavaScript で書かれています。この不具合が見つかったケースを、CODE Polyglot で10言語の「よくある書き方」で回した結果です(言語を返した答えごとにまとめ、赤い値は実際に返した間違った答え)。 JavaScript は 3件中3件で外れました。
| ケース | 正解 | よくある書き方の答え(10言語) |
|---|---|---|
| c005利息がちょうど 3.5円 |
|
|
| c006複利の利息がちょうど 1,002.5円 |
|
|
| c007複利の利息がちょうど 50,062.5円 |
|
|
何が起きていたか
元本・年利・年数から利息と税引後の金額を出すツールで、3つの点がずれていました。
- 内訳がそろわない: 利息・税額・税引後の利息・元利合計を、それぞれ別々に円へ四捨五入して表示していたので、「利息 − 税額 = 税引後の利息」にならないことがありました
- 利息が1円少ない: 10万円を年0.5%の複利で2年預けると、利息は 1,002.5円で、四捨五入して 1,003円が正解です。ツールは 1,002円 と表示していました
- 税額の計算が実務と違う: 利息 × 20.315% を1回で計算していました。銀行の源泉分離課税は、所得税・復興特別所得税 15.315% と住民税 5% を、それぞれ1円未満切り捨てにします
どのくらいの入力で起きていたか
元本9通り(1万〜1,000万円)× 年利15通り(0.001〜5%)× 1〜30年 × 単利・複利 の 8,100通り で調べました(2026-10-16)。
| ずれ | 件数 |
|---|---|
| 「利息 − 税額 ≠ 税引後の利息」になる(正確に計算しても起きる) | 1,445通り |
| 利息が1円少ない(2進数の小数の誤差) | 9通り |
内訳のずれは、2進数の誤差ではなく、丸め方の設計によるものです。正確な値で計算しても、別々に四捨五入すると合計が合わなくなります。
どうやって見つかったか
CODE Polyglot の仕様 預金利息の計算 を作る前に、元のツールの式を正確な値と比べました(2026-10-16)。利息の1円ずれより、内訳のずれの方がずっと多いことが分かったので、仕様では税を実務どおりに決め、内訳が必ずそろう定義にしました。
原因
- 複利の
principal * Math.pow(1 + r, years)は、2進数の小数で計算すると、1,002.5 が 1002.4999999999709 になります(解説) - 表示用の関数
yen()が、利息・税額・税引後の利息のそれぞれをMath.roundしていたので、3つの数の関係が崩れていました
どう直したか
計算の部分を calc.js に分け、年利を分数(BigInt の分子・分母)にして、利息を正確に求めてから1回だけ円に四捨五入するようにしました。税額と税引後の金額は、その円の利息から整数で求めるので、内訳が必ずそろいます。
- var TAX_RATE = 0.20315; // 所得税・復興特別所得税・住民税 - grossTotal = principal * Math.pow(1 + r, years); - var tax = interest * TAX_RATE; - var netInterest = interest - tax; + // 整数年の年複利は BigInt 冪で厳密。利息 = pn×((rd+rn)^y − rd^y) / (pd×rd^y) + interest = roundYen(pn * (powBase - powRd), pd * powRd); + var tax = taxOf(interest); + var net = interest - tax;
+ function roundYen(num, den) { + return (2n * num + den) / (2n * den); + } + function taxOf(interest) { + return (interest * 15315n) / 100000n + (interest * 5n) / 100n; + }
画面の税額の表記も「税額(所得税等15.315%・住民税5%)」に直しました。
確かめたこと
- 修正後の本番の
calc.js(コミット c541ae64)で、整数の年数の範囲の14,111通り(無作為6,000通り・上の8,100通り・正解表11件)がすべて正解と一致(2026-10-17) - シルギア側のテスト15件と、ツール全体のテスト291件がすべて通過
- 本番の画面で、10万円・年0.5%・2年・複利 → 利息1,003円・税203円・税引後の利息800円、100万円・年0.2%・10年・複利 → 利息20,181円・税4,099円 と表示されることを確認(シルギア側の報告)