浮點數運算與數值表示

次正規數

想像一把尺,其最小刻度落在比方 0.001,而在 0 與 0.001 之間什麼刻度都沒有。若一次測量得到 0.0003,你將被迫粗暴地把它捨入到 0 或 0.001——一次很大的相對跳動。浮點數在零的正上方面對同樣的斷崖,而次正規數(subnormal number)就是加在那最後一道間隙內的額外細刻度,讓落向零的過程平緩、不再突兀。

正規化數都具有 1.f * 2^e 的形式,但指數 e 不能低於某個最小值 e_min。次正規數(也叫非正規數 denormal)使用那個最小指數,同時「捨棄」隱含的領先 1,呈 0.f * 2^e_min 的形式。隨著小數部分的領先位元變為零,數值能一路平滑地縮小到可能的最小非零數,但代價是有效位元越來越少——次正規數以精度換取觸及範圍。這套機制稱為「漸進下溢」:低於最小正規數的值不會直接塌縮成 0(那叫「沖刷至零」),而是一步步退化。

漸進下溢使一個程式悄悄依賴的性質得以成立:若 x 與 y 是不同的浮點數,則 x - y 永不恰為 0,於是「if (x != y) 計算 1/(x-y)」這類程式不會爆掉。若沒有次正規數,兩個相異的數相減的真實結果可能小於最小正規數而被沖刷成 0。實務上的告誡:在某些硬體上,使用次正規數計算「明顯更慢」(晶片可能陷入微碼處理),所以性能關鍵的程式有時會啟用「沖刷至零」模式——明知會放棄平緩著陸以換取速度。

最小的正規化雙精度數約為 2.225e-308。在其下,次正規數一路延伸至約 4.9e-324(最小的正雙精度數),但像 1e-320 這樣的數現在只帶有寥寥幾個有效位元,而非平常的約 16 位。把兩個中等偏小的正規數相乘可能落入這個次正規區,並悄悄損失精度。

次正規數填補通往零的最後一道間隙——代價是精度。

次正規數並非「壞掉」的小數——它們是刻意設計、用來提供漸進下溢的特性。但它們的精度降低,而「沖刷至零」模式(在 GPU 上很常見)會悄悄把它們全部變成 0。

又称
denormal numberdenormalized number次正規數非正規數