どの言語で起きるか
シルギアのツールは JavaScript で書かれています。この不具合が見つかったケースを、CODE Polyglot で10言語の「よくある書き方」で回した結果です(言語を返した答えごとにまとめ、赤い値は実際に返した間違った答え)。 JavaScript は 2件中2件で外れました。
| ケース | 正解 | よくある書き方の答え(10言語) |
|---|---|---|
| c002SNS・月22.5GB(整数への四捨五入が .5) |
|
|
| c003音楽・月ちょうど7GB(プランの境目) |
|
|
何が起きていたか
用途と利用時間から1か月の通信量(ギガ)と目安のプランを出すツールで、境目の値が反対側に落ちていました。
- ちょうど7GB なのに「10GB プラン」: 音楽ストリーミング(0.08GB/時)を1日3.5時間・月25日使うと、0.08 × 3.5 × 25 = 7GB ちょうどです。目安のプランは「7GB 以下」なので、正解は「7GB プラン」です。ツールは 「10GB プランが目安」 と表示していました
- 22.5GB が「22 GB」: SNS(0.3GB/時)を1日3時間・月25日使うと 22.5GB で、整数に四捨五入して 23 GB が正解です。ツールは 22 GB と表示していました
どのくらいの入力で起きていたか
用途の選択肢にある1時間あたりの通信量11種類(0.04〜7.0GB)× 1日の利用時間 0〜24時間(0.5時間刻み)× 月の利用日数 1〜31日の 16,709通り で、正確な値と比べました。
| ずれ | 件数 |
|---|---|
| 1か月の通信量の表示が 0.1GB(10GB 以上では 1GB)少ない | 16,709通り中182通り |
| 目安のプランが1つ上になる | 16,709通り中4通り |
1日の通信量の表示は日数によらないので、11種類 × 49通りの 539通り で数えました。539通り中20通りで 0.1GB 少なく表示していました(例: 0.3GB/時 × 4.5時間 = 1.35GB → 1.3 GB、正しくは 1.4 GB)。
プランが1つ上になった4通りは、どれも月の通信量がちょうど7GB の組み合わせでした(0.08GB/時 × 3.5時間 × 25日 など)。「3GB で使える時間」「20GB で使える時間」は、16,709通りすべてで正しく表示されていました。
どうやって見つかったか
CODE Polyglot の仕様 データ通信量(ギガ)の目安 を作るとき、元のツールと同じ式を4言語で書いて、正確な値と突き合わせました(2026-10-11)。正解表11件のうち、c002(22.5GB)と c003(ちょうど7GB)を4言語とも外しました。元のツールと同じ式を Node で評価すると、公開中のツールも11件中この2件で正解と違うことがわかりました。
原因
- 0.08 や 0.3 は2進数の小数では正確に表せません。0.08 × 3.5 × 25 は 7.000000000000001 になり、「7 以下」を満たさずに次の 10GB プランへ進みます。0.3 × 3 × 25 は 22.499999999999996 になり、0.5 に届かないので
toFixed(0)で 22 に切り下がります(解説)
どう直したか
計算の部分を calc.js に分けました。1時間あたりの通信量・時間・日数を十進の文字列のまま整数の分子・分母(BigInt)にして掛け、プランの境目との比較と、表示の四捨五入を整数で行います。表示の形(10GB 以上は整数、1GB 以上は小数第1位、1GB 未満は MB)は変えていません。
- var monthly = perDay * days; - if (gb >= 10) return gb.toFixed(0) + " GB"; - if (monthlyGb <= tiers[i]) return tiers[i] + "GB プランが目安"; + var monthly = mul(perDay, d); // GB/月 + return String(roundHalfUpDiv(n, d)) + " GB"; + // r <= tier ⇔ r.n <= tier * r.d + if (r.n <= BigInt(tiers[i]) * r.d) return tiers[i] + "GB プランが目安";
確かめたこと
- 本番が配信している
calc.js(リポジトリと同じ内容、コミット 011c958e)で、無作為な100,000通りがすべて正解と一致(2026-10-11) - 本番のページで「7.0 GB・7GB プランが目安」「23 GB」と表示されることを確認
- シルギア側のテスト16件がすべて通過