CODE Polyglot / 直した不具合

不快指数が 0.1 少なくなり、露点がわずかに負のとき「−0.0℃」と表示する

気温0℃・湿度50% → 不快指数 39.1(正しくは39.2)、0.1℃・99% → 露点 −0.0℃(正しくは0.0℃)

どの言語で起きるか

シルギアのツールは JavaScript で書かれています。この不具合が見つかったケースを、CODE Polyglot で10言語の「よくある書き方」で回した結果です(言語を返した答えごとにまとめ、赤い値は実際に返した間違った答え)。 JavaScript は 5件中4件で外れました。

ケース正解よくある書き方の答え(10言語)
c003不快指数がちょうど 66.35
di
66.4
feel
快適
dew
14.4
abs_humidity
12.1
risk
中
  • Python・Go・JavaScript・C#・Rust・Swiftdi"66.3"
  • PHP・Java・Ruby・Kotlin✓ 正解
c004不快指数がちょうど 63.05
di
63.1
feel
何も感じない
dew
-12.5
abs_humidity
1.7
risk
低い
  • Python・Go・JavaScript・C#・Rust・Swiftdi"63.0"
  • PHP・Java・Ruby・Kotlin✓ 正解
c002不快指数がちょうど 65.25(2進数でも誤差なし)
di
65.3
feel
快適
dew
9.3
abs_humidity
8.7
risk
低い
  • Python・Go・C#・Rust・Swiftdi"65.2"
  • PHP・JavaScript・Java・Ruby・Kotlin✓ 正解
c008露点がわずかに負(−0.003℃)
di
34.7
feel
寒い
dew
0.0
abs_humidity
4.8
risk
低い
  • Python・Go・JavaScript・Java・C#・Rust・Kotlin・Swiftdew"-0.0"
  • PHP・Ruby✓ 正解
c009露点がわずかに負(−0.04℃)
di
32.3
feel
寒い
dew
0.0
abs_humidity
4.8
risk
低い
  • Python・Go・JavaScript・Java・C#・Rust・Ruby・Kotlin・Swiftdew"-0.0"
  • PHP✓ 正解

何が起きていたか

気温と湿度から不快指数・露点・絶対湿度を出すツールで、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件がすべて通過

← 直した不具合の一覧へ