どの言語で起きるか
シルギアのツールは JavaScript で書かれています。この不具合が見つかったケースを、CODE Polyglot で10言語の「よくある書き方」で回した結果です(言語を返した答えごとにまとめ、赤い値は実際に返した間違った答え)。 JavaScript は 5件中4件で外れました。
| ケース | 正解 | よくある書き方の答え(10言語) |
|---|---|---|
| c003不快指数がちょうど 66.35 |
|
|
| c004不快指数がちょうど 63.05 |
|
|
| c002不快指数がちょうど 65.25(2進数でも誤差なし) |
|
|
| c008露点がわずかに負(−0.003℃) |
|
|
| c009露点がわずかに負(−0.04℃) |
|
|
何が起きていたか
気温と湿度から不快指数・露点・絶対湿度を出すツールで、2つの表示がずれていました。
- 不快指数が 0.1 少なくなる: 気温0℃・湿度50% の不快指数は 39.15 ちょうどで、四捨五入して 39.2 が正解です。ツールは 39.1 と表示していました。20℃・70%(66.35 → 66.4 が正解)も 66.3 でした
- 露点が「−0.0℃」になる: 気温0.1℃・湿度99% の露点は −0.038…℃ で、小数第1位にすると 0.0℃ です。ツールは −0.0℃ と表示していました
どのくらいの入力で起きていたか
気温 −20.0〜40.0℃(0.1℃刻み)× 湿度 1〜100% の 60,100通り で、正確な値と比べました。
| ずれ | 件数 |
|---|---|
| 不快指数が 0.1 少ない | 20通り |
| 露点が「−0.0」 | 57通り |
露点(対数)と絶対湿度(累乗)の値そのものは、60,100通りすべてで正しく表示されていました。
どうやって見つかったか
CODE Polyglot の仕様 露点・不快指数の計算 を作るとき、元のツールと同じ式を8言語で書いて、正確な値と突き合わせました(2026-10-15)。JavaScript のよくある書き方(元のツールと同じ書き方)は、正解表17件中11件しか正解せず、外れたケースがそのまま元のツールの不具合でした。
原因
- 不快指数 0.81 × T + 0.01 × RH × (0.99 × T − 14.3) + 46.3 は、割り切れる小数(39.15 など)になることがあります。2進数の小数で計算すると 39.149999… になり、
toFixed(1)で 39.1 に切り捨てられます(解説) toFixed(1)は、−0.038 のような負の数を「−0.0」と書きます(解説)
どう直したか
計算の部分を calc.js に分け、不快指数を「10万倍した整数」で計算するようにしました。気温は小数第1位まで、湿度は整数なので、2進数の小数を一度も通らずに四捨五入できます。
- var di = 0.81 * temp + 0.01 * humid * (0.99 * temp - 14.3) + 46.3; - var diText = di.toFixed(1); - var dewText = dew.toFixed(1); + // 不快指数 × 100000(整数・BigInt)を小数第1位に四捨五入(0.5 は 0 から遠い方へ) + var M = 81000n * tn * Q + 990n * tn * hn - 14300n * hn * P + 4630000n * P * Q; + var r = (a * 2n + den) / (den * 2n); + var diInfo = computeDI(String(temp), String(humid)); + var dewText = fixed1(dew); // "-0.0" は "0.0" に
+ export function fixed1(x) { + var s = Number(x).toFixed(1); + return s === "-0.0" ? "0.0" : s; + }
気温や湿度に小数第2位以下が入っても、同じ式を分数(BigInt)で計算します。湿度100% のときは、露点を気温そのものにしました(数式の上でちょうど等しいため)。
確かめたこと
- 修正後の本番の
calc.js・app.js(コミット dcd106fa)で、60,100通りすべてが正解と一致(2026-10-16) - シルギア側のテスト18件(正解表のケースを含む)と、ツール全体のテスト251件がすべて通過