どの言語で起きるか
シルギアのツールは JavaScript で書かれています。この不具合が見つかったケースを、CODE Polyglot で10言語の「よくある書き方」で回した結果です(言語を返した答えごとにまとめ、赤い値は実際に返した間違った答え)。 JavaScript は 6件中6件で外れました。
| ケース | 正解 | よくある書き方の答え(10言語) |
|---|---|---|
| c004境目ちょうど100・2進数で小さく入る |
|
|
| c005境目ちょうど115・2進数で小さく入る |
|
|
| c006境目ちょうど145・2進数で小さく入る |
|
|
| c007境目ちょうど160・2進数で小さく入る |
|
|
| c009指数が .x5 ちょうど |
|
|
| c010指数が .x5 ちょうど(2) |
|
|
何が起きていたか
身長と体重から子どもの体格の目安(ローレル指数)を出し、「やせ・やせ気味・ふつう(標準)・太り気味・肥満」に分けるツールで、指数がちょうど区分の境目になる入力を、下の区分と判定していました。
- 身長 130cm・体重 21.97kg: 21.97 ÷ 1.3³ × 10 は 100 ちょうどで、「やせ気味」が正しい区分です。ツールは「やせ」と出していました
- 160cm・59.392kg(指数 145 ちょうど)は「ふつう(標準)」、110cm・21.296kg(指数 160 ちょうど)は「太り気味」と出ていました(正しくは「太り気味」「肥満」)
指数の表示にも、四捨五入のずれがありました。
- 身長 160cm・体重 12.8kg: 指数は 31.25 ちょうどで、小数第1位に四捨五入すると 31.3 です。ツールは 31.2 と出していました
どのくらいの入力で起きていたか
| 確かめたこと | 入力 | ずれ |
|---|---|---|
| 区分の境目ちょうど(身長 100.0〜180.0cm で、体重が小数4桁以内で書ける入力) | 44通り | 19通りで下の区分 |
| 指数の表示(身長 100.0〜180.0cm × 体重 10.0〜80.0kg、0.1刻み) | 561,501通り | 3通り(31.25・93.75・156.25 が切り下がる) |
ふだんの入力(体重を 0.1kg 刻みで入れる)ではまれですが、境目ちょうどの人には、区分が1つ下に出ていました。
どうやって見つかったか
CODE Polyglot の20本目の仕様 ローレル指数 を作る前に、元のツールの式を Node で評価して、上の数を確かめました(2026-10-30)。同じ仕様を10言語で書いたよくある書き方も、同じ4件(境目)と2件(表示)で落ちました。
原因
- 21.97 ÷ 1.3³ × 10 を2進数の小数で計算すると 99.99999999999997 になります。区分は
index < 100で決めていたので、「やせ」に入りました(解説) - 31.25 も2進数の小数では 31.249999999999996 になり、
toFixed(1)で 31.2 と書かれていました(解説)
どう直したか
計算を新しいファイル calc.js に分け、入力の文字列(「130」「21.97」)を 分数(BigInt)のまま計算するようにしました。
- 区分は、割り算をせずに掛け算で比べる(体重 × 10⁷ と 境目 × 身長³ を比べる)。丸める前の正確な指数で決まる
- 指数とふつうの体重の範囲は、正確な値を小数第1位に1回だけ四捨五入する(0.5 ちょうどは大きい方へ)
確かめたこと
CODE Polyglot の検証(tools/shirugear-verify/。本番の app.js と calc.js をそのまま動かし、画面の文字を正確な分数の正解と比べる)で確かめました。
入力は次の 1,071,834通り です。
- 身長 100.0〜180.0cm × 体重 10.0〜80.0kg(0.1刻み)
- 整数の身長 × 体重 0.01刻み
- 境目ちょうどになる入力
1e2のような書き方- エラーになる入力
比べたのは、画面の指数・区分・ふつうの体重の範囲・説明の行です。
| 版 | 不一致 |
|---|---|
| 直す前の本番 | 1,071,834通り中31通り(指数の表示 14・区分 17) |
| 修正(d23fd309b)・本番に反映する前 | 1,071,834通り中0通り |
本番に反映したあと(2026-10-30。本番の app.js・calc.js がこのコミットと同じことも確認) | 1,071,834通り中0通り |