CODE Polyglot / 直した不具合

BMI がちょうど25・30・35・40のとき下の区分と判定する(25ちょうどで目標の文言が消える)

身長160cm・体重64kg(BMI 25.0)→「普通体重」(正しくは「肥満(1度)」)

何が起きていたか

身長と体重から BMI を出し、日本肥満学会の基準で「低体重(やせ)・普通体重・肥満(1度〜4度)」に分けるツールで、BMI がちょうど区分の境目になる入力を、下の区分と判定していました。

  • 身長 160cm・体重 64kg: 64 ÷ 1.6² は 25 ちょうどで、「肥満(1度)」が正しい区分です。ツールは「普通体重」と出していました
  • 110cm・36.3kg(BMI 30 ちょうど)は「肥満(1度)」と出ていました(正しくは「肥満(2度)」)

区分のほかに、「普通体重まであと何kg」という目標の文言にも、境目のずれがありました。

  • BMI がちょうど25のとき、目標の文言が消えていた(100.0cm・25.0kg)
  • 減らす量が 0.05kg に満たないのに「あと約 0.0kg 減が目安です」と出ていた(100.1cm・25.1kg)

どのくらいの入力で起きていたか

身長 100.0〜200.0cm × 体重 10.0〜150.0kg(0.1刻み)の 1,402,401通り で、正確な値と比べました。

画面のどこか直す前
区分(とコピーの文字・目盛りの読み上げ)9通り
目標の文言487通り

どうやって見つかったか

CODE Polyglot の ローレル指数 で同じ種類の不具合(直した不具合)が見つかりました。そこで、シルギア側が、同じように体重を身長の累乗で割って区分を決めるツールを探して直しました。CODE Polyglot は、直したコードを本番に出す前と出したあとに、全通りで確かめました。

本番に出す前の確認では、もう1つずれが見つかりました。差(体重 − 適正体重)や減らす量がちょうど 0.05kg のとき、「ほぼ標準」「あと約 0.1kg 減」の分かれ目がずれていました(例 150cm・49.45kg、170.0cm・72.3kg)。シルギアは、ここも直してから本番に出しました。

原因

  • 64 ÷ 1.6² を2進数の小数で計算すると 24.999999999999996 になります。区分は bmi < 25 で決めていたので、「普通体重」に入りました
  • 0.05kg の分かれ目も、2進数の小数で引き算した結果(0.04999… や 0.05000…01)を 0.05 と比べていました

どう直したか

計算を新しいファイル calc.js に分けました。入力の文字列(「160」「64」)を分数(BigInt)のまま扱い、区分と 0.05kg の分かれ目を、割り算をせず掛け算で比べるようにしました。BMI・適正体重などの 0.1 単位の表示は、もともと正しく出ていたので変えていません。

確かめたこと

CODE Polyglot の検証(tools/shirugear-verify/。本番の app.js と calc.js をそのまま動かし、画面の文字を正確な分数の正解と比べる)で確かめました。

入力は次の 1,685,752通り です。

  • 上の 1,402,401通り
  • 整数の身長 × 体重 0.01刻み
  • 身長 0.1cm ごとに BMI が 18.5・25・30・35・40 ちょうどになる体重
  • 差・減らす量がちょうど ±0.05kg になる体重
  • 1e2 のような書き方
  • エラーになる入力

比べたのは、BMI・区分・適正体重・差・目標の文言・早見表・目盛りの読み上げ・コピーの文字です。

版不一致
直す前の本番1,685,752通り中5,006通り
1回目の修正(3bb9c6640)1,685,752通り中1,543通り(0.05kg ちょうどの分かれ目)
2回目の修正(e82a5a944)・本番に反映したあと(2026-10-30。本番の app.js・calc.js がこのコミットと同じことも確認)1,685,752通り中0通り

← 直した不具合の一覧へ