何が起きていたか
乳幼児の身長と体重からカウプ指数を出し、年齢区分ごとの基準で「やせすぎ〜太りすぎ」に分けるツールで、指数が小数第2位でちょうど5になる入力を、下に丸めていました。
- 身長 100cm・体重 17.55kg: 17.55 × 1000 ÷ 100² × 10 は 17.55 ちょうどで、小数第1位に四捨五入すると 17.6 です。ツールは 17.5 と出していました
- 40.0cm・8.04kg は 50.25 ちょうどで、正しくは 50.3 です。ツールは 50.2 と出していました
どのくらいの入力で起きていたか
身長 30.0〜140.0cm(0.1刻み)× 体重 1.00〜40.00kg(0.01刻み)の 4,295,111通り で、正確な値と比べると、43通りで表示が 0.1 小さく出ていました。区分は丸めたあとの指数で決める仕様ですが、この範囲では区分まで変わる入力はありませんでした。
どうやって見つかったか
CODE Polyglot の ローレル指数 で同じ種類の不具合(直した不具合)が見つかりました。そこで、シルギア側が、同じように体重を身長の累乗で割るツールを探して直しました。CODE Polyglot は、直したコードを本番に出す前と出したあとに、全通りで確かめました。
原因
- 17.55 × 1000 ÷ 100² × 10 を2進数の小数で計算すると、17.55 よりわずかに小さい値になります。
Math.round(指数 × 10) / 10で丸めていたので、17.5 になりました
どう直したか
計算を新しいファイル calc.js に分け、入力の文字列を分数(BigInt)のまま計算して、小数第1位に1回だけ四捨五入するようにしました(0.5 ちょうどは大きい方へ)。
確かめたこと
CODE Polyglot の検証(tools/shirugear-verify/。本番の app.js と calc.js をそのまま動かし、画面の文字を正確な分数の正解と比べる)で確かめました。
入力は次の 6,016,972通り です。
- 上の 4,295,111通り(年齢区分は入力ごとに4つを順に)
- 身長 0.1刻み × 体重 0.1刻み × 年齢区分4つ
1e2のような書き方- エラーになる入力
比べたのは、指数・区分・説明の行・ふつうの範囲・コピーの文字です。
| 版 | 不一致 |
|---|---|
| 直す前の本番 | 6,016,972通り中44通り(指数の表示とコピーの文字) |
| 修正(0db43e57c)・本番に反映する前 | 6,016,972通り中0通り |
本番に反映したあと(2026-10-30。本番の app.js・calc.js が e82a5a944 と同じことも確認) | 6,016,972通り中0通り |