一次點擊,螢幕上站著兩個互不相干的數
在預設那組男性輸入上(身高 170 cm、體重 70 kg、30 歲、腰圍 80 cm、頸圍 38 cm),點一次「計算體脂率」,頁面會同時給出兩個百分比:大字那格是 13.7%,下面那行小字是 19.8%,相差 6.1 個百分點。換成女性預設那組(同樣參數再加臀圍 95 cm),結果是 25.6% 與 30.6%,差 5.0 個百分點。
第一反應通常是「下面那個更粗、上面那個更細」。但它們不是同一個公式的兩檔精度,而是兩套公式,輸入集合完全不相交:13.7% 走美國海軍體圍法,只讀身高與圍度,式子裡沒有體重這一項;19.8% 走由 BMI 換算的那條式子,只讀身高、體重、年齡、性別,式子裡沒有腰圍這一項。我把 體脂率計算器 模板裡那兩條式子原樣抽出來跑了一遍,下面每個數字都是同一次點擊能重現的輸出,不是估計。
把體重推滿 10 kg,只有一個數在動
最能說明這層關係的是改體重。取男 175 cm、腰圍 90 cm、頸圍 38 cm、32 歲這一組,把體重從 73 kg 推到 83 kg:大字那側始終是 20.7%,一個小數都沒變;下面那側從 19.8% 走到 23.7%,順帶把同行的 BMI計算器 口徑也推著從 23.8 走到 27.1。同一隻滑桿推到底,一個紋絲不動,另一個整檔搬家。
年齡和性別也只餵給下面那個數。性別切一次,Deurenberg 那側恆差 10.8 個百分點,因為換算式裡的性別項就是 male ? 1 : 0 這一個數;年齡從 20 推到 60,它漲 9.2 個百分點(式子裡是 0.23 * age),而海軍法停在原值上,差 0.0。
腰圍 1 cm 到底值多少
圍度這一側比多數人以為的靈敏。男性基準(身高 175、頸圍 38、腰圍 90)上,腰圍動 1 cm 就是 0.7 到 0.8 個百分點,動 5 cm 是 3.4 到 3.8 個百分點。女性基準(身高 163、腰 76、頸 33、臀 96)上,腰、頸、臀各自動 1 cm 都是 0.5 個百分點,動 5 cm 是 2.5 個百分點。頸圍與腰圍同量反號,因為式子裡只出現 waist - neck 這一個差;女性那條多出的臀圍與腰圍同號。
圖 1:兩個數並排,餵給它們的輸入一格都不重疊,不是同一個量的兩次近似。
圖 2:只動圍度、其餘項不變時海軍法那一側的位移;頸圍與腰圍同量反號,女性臀圍與腰圍同向。
兩個數對不上是常態,但幅度看人
這 12 組現實裡真會填進去的參數(含首屏兩組預設值)我逐條跑過:兩個數的絕對差最小 0.1 個百分點、最大 6.1 個百分點、平均 2.44,其中 2/12 組按頁面自己的閾值分別查檔會落到不同檔位。只取 10 組真人輸入看帶符號的差,範圍是 -4.3 到 +1.3、平均 1.82——方向都不固定,沒人保證大字那位一定比小字那位低。
| 輸入 | 大字(海軍法) | 小字(BMI 換算) |
|---|---|---|
| 男 170 / 70 kg / 30 歲 / 腰 80 / 頸 38 | 13.7% | 19.8% |
| 女 同參數 + 臀 95 | 25.6% | 30.6% |
| 女 166 / 60 kg / 60 歲 / 腰 78 / 頸 32 / 臀 98 | 30.2% | 34.5% |
| 男 175 / 腰 90 / 頸 38 / 32 歲 / 83 kg | 20.7% | 23.7% |
唯一的攔截只裝在男性那一側
整套邏輯裡只有一條輸入校驗:男性那一支要求腰圍嚴格大於頸圍,等於也不放行。實測腰 80 頸 80 與腰 80 頸 81,頁面只彈一句「腰圍需大於頸圍」然後直接返回,螢幕上先前那次的結果一位都不改——舊數字留在原地,很容易被讀成新算出來的。女性那一支在兩條式子之間沒有任何判斷:同樣腰 80 頸 80,配上臀 95 照樣得出 3.1%;腰 70 頸 80 臀 95 得出 -3.8%。
這兩組入參全在滑桿量程之內。更極端的一組也合法:女 163 cm / 58 kg,腰 50、頸 80、臀 60,得出 -59.5%,同行的脂肪重量寫著 -34.5 kg、瘦體重 92.5 kg 比體重本身還大,而檔位那一格印的是「必需脂肪」;男 220 cm、腰 50、頸 49 得出 -95%。守衛管的是圍度之間的大小關係,不管結果像不像話。
只有另一類必須往程式碼裡注入才碰得到:女性那條式子的對數入參 腰 + 臀 - 頸 一旦非正就走到 NaN 或 -Infinity,而 UI 把這條路堵死了。6 個輸入全是 range,模板裡 step= 出現 0 次所以只能取整數,越界值寫進去會被瀏覽器夾回量程(實測 30→50、250→200、空字串→125、abc→125、75.5→76)。腰圍最小 50 加臀圍最小 60 減頸圍最大 80,這個差的最小可能值是 30;1,192,296 組整數圍度全枚舉一遍,非正的有 0 組。
壓線那一下,兩句話互相打臉
檔位全部用嚴格小於:男性四道門檻是 6、14、18、25,女性是 14、21、25、32。實測 24.9 寫「正常水平」、25.0 寫「肥胖」;男性 6.0 已經進了「運動員水平」,5.9 留在上一檔。麻煩在下面那行建議句用的是另一個比較條件(體脂率大於 25 才換話術),於是 25.0 這組數字同時打出「體脂偏高」和「保持當前運動和飲食習慣,定期監測體脂變化」兩句相反的話,女性的 32.0 同理。上面引號裡那幾格字樣只是頁面上印出的字串,不是測量或對照出來的屬性。
它們只是公式與常量的直接輸出
把這個頁面當成兩台互不通氣的計算器看待就順了:大字那位只對身高與圍度有反應,小字那位只對身高、體重、年齡、性別有反應,檔位那一行則是把其中一個數拿去和四道寫死的常量比大小。這類把常量印成結論的寫法站內不止一處,基礎代謝那篇 裡也碰到過同樣的讀法問題:螢幕上不會出現「這是判斷,不是測量」這半句話。至於誰高誰低,它隨輸入變號,不構成結論。
Q:兩個數我該看哪個?
頁面沒寫優先級,我也不替它寫。它們不是同一個量的兩次近似,而是各自只對一半輸入有反應;12 組輸入裡兩者的絕對差最大到 6.1 個百分點,把它們當成互為驗證是讀錯了版式。
Q:為什麼我改了體重,那個數一點沒動?
因為大字那位的式子裡根本沒有體重項。73 kg 推到 83 kg,它一直停在 20.7%;同一次改動把小字那位從 19.8% 推到 23.7%。想知道某個輸入有沒有參與,看它動不動就夠了。
Q:卷尺量得不準,影響有多大?
男性基準上腰圍 1 cm 就是 0.7 到 0.8 個百分點,5 cm 是 3.4 到 3.8;女性 1 cm 是 0.5,5 cm 是 2.5。而壓線的容錯是零——24.9 與 25.0 分屬兩檔,一次讀數的手勁足以決定螢幕上那句建議寫什麼。