CODE Polyglot / 直した不具合

指数がちょうど100・115・145・160のとき、下の区分と判定する(指数の表示も 0.05 ちょうどで切り下がる)

身長130cm・体重21.97kg(指数100ちょうど)→「やせ」(正しくは「やせ気味」)、160cm・12.8kg → 31.2(正しくは31.3)

どの言語で起きるか

シルギアのツールは JavaScript で書かれています。この不具合が見つかったケースを、CODE Polyglot で10言語の「よくある書き方」で回した結果です(言語を返した答えごとにまとめ、赤い値は実際に返した間違った答え)。 JavaScript は 6件中6件で外れました。

ケース正解よくある書き方の答え(10言語)
c004境目ちょうど100・2進数で小さく入る
index
100.0
category
やせ気味
normal_low
25.3
normal_high
31.9
  • Go・JavaScript・Java・C#・Rust・Kotlin・Swiftcategory"やせ"
  • PHP・Python・Ruby✓ 正解
c005境目ちょうど115・2進数で小さく入る
index
115.0
category
ふつう(標準)
normal_low
25.3
normal_high
31.9
  • Go・JavaScript・Java・C#・Rust・Kotlin・Swiftcategory"やせ気味"
  • PHP・Python・Ruby✓ 正解
c006境目ちょうど145・2進数で小さく入る
index
145.0
category
太り気味
normal_low
47.1
normal_high
59.4
  • PHP・Python・Go・JavaScript・Java・C#・Rust・Ruby・Kotlin・Swiftcategory"ふつう(標準)"
c007境目ちょうど160・2進数で小さく入る
index
160.0
category
肥満
normal_low
15.3
normal_high
19.3
  • PHP・Python・Go・JavaScript・Java・C#・Rust・Ruby・Kotlin・Swiftcategory"太り気味"
c009指数が .x5 ちょうど
index
31.3
category
やせ
normal_low
47.1
normal_high
59.4
  • PHP・Python・Go・JavaScript・Java・C#・Rust・Ruby・Kotlin・Swiftindex"31.2"
c010指数が .x5 ちょうど(2)
index
156.3
category
太り気味
normal_low
47.1
normal_high
59.4
  • PHP・Python・Go・JavaScript・Java・C#・Rust・Ruby・Kotlin・Swiftindex"156.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通り

← 直した不具合の一覧へ