どの言語で起きるか
シルギアのツールは JavaScript で書かれています。この不具合が見つかったケースを、CODE Polyglot で10言語の「よくある書き方」で回した結果です(言語を返した答えごとにまとめ、赤い値は実際に返した間違った答え)。 JavaScript は 3件中3件で外れました。
| ケース | 正解 | よくある書き方の答え(10言語) |
|---|---|---|
| c0030.05 の境目・かつおだし 45ml |
|
|
| c0040.05 の境目・かつおだし 335ml |
|
|
| c0050.05 の境目・煮干しだし 155ml |
|
|
何が起きていたか
水の量とだしの種類から、昆布・かつお節などのグラム数を出すツールで、材料のグラム数が 0.1g 少なくなることがありました。
- 水 45ml・かつおだし(かつお節 3%): 45 × 3% = 1.35g で、小数第1位に四捨五入して 1.4g が正解です。ツールは 1.3g と表示していました
- 水 335ml・かつおだし(10.05g)は 10g(正しくは 10.1g)、水 155ml・煮干しだし(4.65g)は 4.6g(正しくは 4.7g)でした
どのくらいの入力で起きていたか
水 1〜5,000ml(1ml刻み)× 割合 1%・2%・3% の 15,000通り で、正確な値と比べました。
| 割合 | 0.1g 少ない |
|---|---|
| 1%(昆布・顆粒だし) | 5,000通り中0通り |
| 2%(かつお節・昆布) | 5,000通り中0通り |
| 3%(かつお節・煮干し) | 5,000通り中66通り |
| 合計 | 15,000通り中66通り |
0.1g 多くなる向きのずれはありませんでした。
どうやって見つかったか
CODE Polyglot の仕様 だし(出汁)の割合計算 を作る前に、元のツールの式を Node で評価して、15,000通り中66通りで 0.1g 少なくなることを確かめました(2026-10-15)。仕様の正解表14件では、c003(45ml)・c004(335ml)・c005(155ml)を、元のツールと同じ書き方の4言語がそろって外しました。
同じ日、シルギア側の品質点検では、このツールは「不具合なし」と判定されていました。式(水の量 × 割合)そのものは正しく、早見表の値も境目に乗らなかったためです。CODE Polyglot から反例(水 45ml・かつおだし → 1.3g)と、15,000通り中66通りというずれの件数を示し、その日のうちに直りました。
原因
- 3 ÷ 100 = 0.03 は2進数の小数では正確に表せません。45 × 0.03 は 1.35 ではなく 1.3499999999999999 になり、0.05 に届かないので四捨五入で 1.3 に切り下がります(解説)
どう直したか
水の量と割合はどちらも整数なので、0.1g を単位にした整数で計算するようにしました。計算の部分は calc.js に分けました。
- return { name: m.name, pct: m.pct, grams: water * (m.pct / 100) }; - var r = Math.round(n * 10) / 10; + return { name: m.name, pct: m.pct, gram: gramLabel(water, m.pct) }; + return Math.floor((w * p * 10 + 50) / 100);
水 × 割合 ÷ 100 を 0.1g 単位で四捨五入すると、⌊(水 × 割合 × 10 + 50) ÷ 100⌋ です。2進数の小数を一度も通りません。
確かめたこと
- 修正後の
calc.js(コミット 7b1b403d)で、15,000通りすべてが正解と一致(2026-10-15) - 本番に反映したあと、本番の
calc.jsで同じ15,000通りの一致を確認 - シルギア側の記録では、テスト全体の227件がすべて通過