可表示數值、精度與運算準確度 (Representable Numbers, Precision and Accuracy)
重點總覽 (Overview)
| 主題 | 核心觀念 | 由什麼決定 |
|---|---|---|
| Representable numbers | 可被該格式「精確表示」的數值集合;落在區間內的值會被 round 到最近的代表數 | exponent 定區間、mantissa 定每區間密度 |
| Precision (精度) | 把數值表示成代表數時的「最大表示誤差」 | mantissa 位數(多 1 bit → 誤差減半) |
| Accuracy (準確度) | 一個運算所引入的「最大運算誤差」 | 執行的運算(rounding、近似演算法) |
| Gap near 0 | normalized 1.M 無法表示接近 0 的數,造成 0 附近巨大空洞 | normalized mantissa 排除了 0 |
| Denormalization | E=0 時改用 0.M、固定 exponent,填平 0 附近空洞(IEEE 採用) | 硬體成本高,早期 CUDA 不支援 |
| Special patterns | E 全 1 → ±∞(M=0) 或 NaN(M≠0);E 全 0 → denorm 或 0 |
保留 bit pattern |
| ULP / rounding | 正確捨入的 add/sub 誤差 ≤ 0.5 ULP;除法/超越函數可能更大 | 結果 mantissa 位數超出格式 |
Precision ≠ Accuracy:precision 是「靜態」的表示能力(看 mantissa 位數),accuracy 是「動態」的運算引入誤差(看運算如何實作)。考試最常混淆這兩者。
可表示數值 (Representable Numbers)
Representable numbers = 該格式能精確表示的數值;任何落在兩代表數之間的值都必須被 round 到其中一個。範例採用 5-bit 格式:1-bit S、2-bit E(excess-1)、2-bit M(省略 "1.")。
正的代表數(每區間 4 個 = 2^N,N=mantissa 位數):
| E (code) | actual exp | 區間 | 代表數 (spacing) |
|---|---|---|---|
00 |
2^-1 | [0.5, 1.0) | 0.5, 0.625, 0.75, 0.875 (2^-3) |
01 |
2^0 | [1.0, 2.0) | 1.0, 1.25, 1.5, 1.75 (2^-2) |
10 |
2^1 | [2.0, 4.0) | 2.0, 2.5, 3.0, 3.5 (2^-1) |
11 |
reserved | — | (∞ / NaN,見下) |
五個觀察 (five observations):
- Exponent bits 定義主要區間 (major intervals) — 區間落在相鄰 2 的次方之間。
- Mantissa bits 定義每區間的代表數個數 — N 個 mantissa bit → 每區間 2^N 個代表數 → 決定 precision。
- 0 不可表示 — no-zero 格式中 0 缺席(嚴重缺陷)。
- 越靠近 0、代表數越密 — 每往 0 移動一個區間,寬度減半(4 → 2 → 1 → 0.5…);絕對值小的數被表示得更精確(區間寬度 = 該區間最大 rounding error)。
- 但「緊鄰 0」處反而出現空洞 — normalized 1.M 排除 0,造成 0 附近最大區間無代表數。
no-zero 格式(正半線;0 不可表示):
0 [====== gap ======] * * * * | * * * * | * * * *
^ 0.5 .625 .875 1.0 1.25 1.75 2.0 2.5 3.0 3.5
| \__ 4 個/區間, spacing 2^-3 _/ \_ spacing 2^-2 _/
0 缺席 + 0..0.5 空洞
觀察 4(越靠近 0 越精確)在「緊鄰 0」處失效(觀察 5)。一般而言,m-bit mantissa 在最接近 0 的區間會比次一區間多引入 2^m 倍 誤差;若演算法用這些小數當分母,誤差會在除法中被放大 → numerical instability。
反正規化 vs 突然下溢 (Denormalization vs Abrupt Underflow)
兩種把 0 納入 並處理 0 附近空洞的方法,IEEE 最終採用 denormalization。
| 方法 | E=0 時的解讀 | 對 0 附近的效果 | 採用情形 |
|---|---|---|---|
| No-zero | 無(沿用 1.M) | 0 不可表示 + 巨大空洞 | 不可用 |
| Abrupt underflow | 一律當作 0 | 0 可表示,但空洞更大(0→1.0 全變 0) | 早期 minicomputer / 高速 ALU(圖簡單快) |
| Denormalization | mantissa 改 0.M,exponent 固定 = 上一區間值 | 均勻填平空洞,最後兩區間 spacing 相同 | IEEE 標準 |
abrupt UF : 0 [========== 更大 gap ==========] | 1.0 1.25 1.5 1.75 | 2.0 ... (E=00 全 → 0)
denormal : 0 0.25 0.5 0.75 | 1.0 1.25 1.5 1.75 | 2.0 ... (spacing 0.25, 均勻!)
\__ 把最後一區間 4 個數攤開填滿空洞 _/
Denormalized 數值公式(n-bit exponent,當 E=0 時):
value = (-1)^S * 0.M * 2^(2 - 2^(n-1))
對 5-bit 範例(n=2):指數 = 2 − 2^1 = 0,故 00001 = 0.01_B × 2^0 = 2^-2 = 0.25。對 IEEE single(n=8):指數 = 2 − 128 = −126,denorm 值 = 0.M × 2^-126。
denormalization 公式複雜、硬體須偵測並切換表示法,高速實作成本極高(中等硬體常引入數千 clock cycle 延遲)。這是早期 CUDA 不支援它的原因。
- compute capability 1.3+:支援 denormalized double-precision
- compute capability 2.0+:支援 denormalized single-precision
精度小結:precision = 把數值表示成代表數的最大誤差;mantissa 每多 1 bit,最大誤差減半。這正是 IEEE double 相對 single 更精確的原因。
特殊位元樣式 (Special Bit Patterns: NaN / Infinity)
IEEE 用保留的 exponent 全 1 / 全 0 樣式表達特殊值(Fig. A.8):
| exponent | mantissa | 意義 |
|---|---|---|
11…1 |
≠ 0 | NaN (Not a Number) |
11…1 |
= 0 | (-1)^S × ∞ |
00…0 |
≠ 0 | denormalized |
00…0 |
= 0 | 0 |
IEEE 標準格式位元配置:
| 格式 | S | E | M | 備註 |
|---|---|---|---|---|
| single | 1 | 8 | 23 | — |
| double | 1 | 11 | 52 | mantissa 多 29 bits → 最大表示誤差降為 single 的 1/2^29;exponent 多 3 bits → 動態範圍更廣 |
Infinity 與 NaN 的產生:
- 所有代表數都落在
-∞ ~ +∞之間。∞由 overflow 產生(如大數 ÷ 極小數);任何代表數 ÷±∞= 0。 - NaN 由無意義運算產生:
0/0、0×∞、∞/∞、∞−∞;也用於標記未初始化資料。
兩種 NaN:
| 類型 | MSB of mantissa | 行為 | 用途 |
|---|---|---|---|
| Signaling NaN | cleared (0) | 作為運算輸入時觸發 exception | 標記未初始化資料、mission-critical 中斷執行 |
| Quiet NaN | set (1) | 運算後產生另一個 quiet NaN,不觸發 exception | 結果印成 "NaN",使用者事後檢視 |
目前 GPU 硬體不支援 signaling NaN(大規模平行執行中難以精確 signaling)。
運算準確度與捨入 (Arithmetic Accuracy and Rounding)
Accuracy = 一個運算引入的最大誤差(與 precision 區分:precision 看 mantissa 位數,accuracy 看「運算如何實作」)。最常見誤差來源為 rounding:結果 mantissa 需要的位數超過格式容量。
Alignment shifting(對齊位移):兩 operand exponent 不同時,較小者的 mantissa 右移直到 exponent 相等,可能使結果位數變多。
範例(5-bit 格式):1.00_B × 2^1 + 1.00_B × 2^-2
指數差 = 3 → 第二個數 mantissa 右移 3 位:
1.00_B × 2^1
+ 0.001_B × 2^1 (= 1.00_B × 2^-2 對齊後)
----------------
= 1.001_B × 2^1 <- 理想結果,需 3 個 mantissa bit (格式只有 2!)
→ round 到 1.01_B×2^1 或 1.00_B×2^1
→ 引入誤差 0.001_B × 2^1 = 最低位權的一半 = 0.5 ULP
ULP (Units in the Last Place) = mantissa 最低位的位權;它是衡量運算誤差的單位。
關鍵準確度規則:
| 運算 | 典型最大誤差 | 說明 |
|---|---|---|
| add / subtract | ≤ 0.5 ULP | 正確捨入硬體;今日所有 CUDA device 的 add/sub 達此準確度 |
| division / 超越函數 (sin, 1/x…) | 可能 > 0.5 ULP | 用 polynomial approximation 實作,項數不足則誤差變大 |
範例(inversion 用近似):理想 1.00_B × 2^1,硬體給 1.10_B × 2^1 → 誤差 = 0.10_B = 最低位權 0.01_B 的 2 倍 = 2 ULP(早期裝置確實有 2 ULP 的 inversion 誤差)。
越多 transistor(越新世代)→ special function unit 用更多近似項 → 算術運算更準確。但快速近似運算的準確度仍可能低於正確捨入,這是使用 hardware intrinsics(如 __sinf)必須權衡的點(見 17-Iterative-MRI-Reconstruction/04-Hardware-Trig-Accuracy-and-Performance-Tuning)。
考試/面試重點 (Exam / Test Patterns)
| 情境 / 關鍵字 | 答案 / 技巧 |
|---|---|
| 「precision 由什麼決定?」 | mantissa 位數;多 1 bit 最大表示誤差減半 |
| 「accuracy 由什麼決定?」 | 執行的運算(rounding / 近似),與 mantissa 位數無關 |
| 「每個 exponent 區間有幾個代表數?」 | 2^N(N = mantissa 位數) |
| 「為何 0 附近有空洞?如何解決?」 | normalized 1.M 排除 0;用 denormalization(E=0 改 0.M)均勻填平 |
| 「denormalized 值怎麼算?」 | (-1)^S × 0.M × 2^(2 - 2^(n-1));single → exp = −126 |
| 「abrupt underflow vs denormalization」 | abrupt UF 把 E=0 全當 0 → 空洞更大;denorm 攤開最後區間 → 空洞消失 |
| 「E 全 1 / M=0」「E 全 1 / M≠0」 | ±∞ / NaN |
| 「什麼產生 NaN?」 | 0/0、0×∞、∞/∞、∞−∞、未初始化資料 |
| 「signaling vs quiet NaN」 | signaling(MSB=0) 觸發 exception;quiet(MSB=1) 傳播不中斷;GPU 不支援 signaling |
| 「正確捨入 add 的最大誤差?」 | 0.5 ULP |
| 「round-to-zero (truncate) 的最大 ULP?」 | 1 ULP(截斷往 0,誤差可達整個最低位權)— 練習題 3 |
| 「除法 / sin 為何誤差 > 0.5 ULP?」 | polynomial approximation 項數不足;補 0 的 mantissa bit |
| 「early CUDA 為何不支援 denorm?」 | 硬體偵測+切換成本高(數千 cycle);cc 1.3+ 支援 double、cc 2.0+ 支援 single |
| 「single → double 準確度差多少?」 | mantissa 多 29 bit → 最大表示誤差降為 1/2^29 |
Related Notes
- 24-Numerical-Considerations/01-Floating-Point-Data-Representation
- 24-Numerical-Considerations/03-Algorithm-Considerations-and-Numerical-Stability
- 17-Iterative-MRI-Reconstruction/04-Hardware-Trig-Accuracy-and-Performance-Tuning
- 10-Reduction/01-Reduction-Fundamentals-and-Simple-Kernel
- 13-Sorting/01-Sorting-Foundations-and-Parallel-Radix-Sort