浮點數運算與數值表示

上溢與下溢

每種浮點數格式都只能命名某個有界大小範圍內的數。把結果推過最大可表示值就「上溢(overflow)」;把它擠到最小可表示非零值之下就「下溢(underflow)」。可想成一個會跑滿格的汽車里程表,或一台太粗、量不出一根羽毛的秤:你想要的那個數在該格式裡根本沒有容身之處。

上溢發生在結果超過最大有限數時(雙精度中約 1.8 * 10^308)。在 IEEE 754 下它不會當掉;結果會變成 +Inf 或 -Inf,並設置上溢旗標,那個無窮接著傳播到計算的其餘部分。下溢發生在某非零結果的大小小於最小正規數時(約 2.2 * 10^(-308))。多虧次正規數,值會「漸進」退化——先變成精度降低的次正規數,最後才到 0——而非直接跳到零,這正是「漸進下溢」的意思。

兩者通常都是「公式撰寫時未顧及尺度」的症狀。經典例子是歐氏長度 sqrt(x^2 + y^2):若 x = 1e200,則 x^2 = 1e400 上溢成 Inf,結果即為 Inf,儘管真實答案是完全可表示的 1e200。解藥是重新縮放:提出最大的大小 m = max(|x|,|y|),再計算 m * sqrt((x/m)^2 + (y/m)^2)——這正是好的函式庫中 hypot 函數所做的。下溢則可能悄悄把一個需要的小量(一個機率、一個殘差)沖刷成 0;補救之道是改在對數空間運算、重新縮放、或重排運算讓中間值保持在範圍內。

在雙精度中計算 exp(1000.0) 會上溢成 +Inf(真值約 10^434 超過 1.8e308),而 exp(-1000.0) 會向 0 下溢。在統計中,把許多機率相乘時這會咬人:數千個接近 0.01 的值的乘積會下溢成 0,所以實務者改為把對數機率相加,只在最後才取指數。

重新縮放或改在對數空間運算,讓值留在格式的範圍內。

上溢成 Inf 很吵、常被察覺;下溢成 0 則無聲,更陰險,因為計算會帶著一個錯誤卻看似合理的小結果繼續跑。尤其要留意小的乘積與指數運算。

又称
overflowunderflow溢位下溢