實數分著整數 (integer) 和小數 (subinteger, fractional) 兩部份,中央是小數點 (decimal point,在二進位是 binal point),小數是實數中比 ±1 小的部份。有時陣,有小數部份的實數嘛叫做小數,有可能是表示著分數的有限小數或循環小數、或是無理數的不循環又無限的小數。
DSP 指令假定 binal point convention 的位置如下表:
| Register Size | Format | Notation | Sign Bit | Extension Bit | Fractional Bit |
|---|---|---|---|---|---|
| 40-bit | Signed | 9.31 | 1 | 8 | 31 |
| Unsigned | 8.32 | 0 | 8 | 32 | |
| 32-bit | Signed | 1.31 | 1 | 0 | 31 |
| Unsigned | 0.32 | 0 | 0 | 32 | |
| 16-bit | Signed | 1.15 | 1 | 0 | 15 |
| Unsigned | 0.16 | 0 | 0 | 16 |
1.31 乘以 1.31 是 2.62,過程中需要右移 31 位、或左移一位後取前半段,以維持 1.31。但在一般 32-bit 處理器,只有整數乘法,且結果沒有 64 bits 或大於 32 bits 的空間,只能存後面 32 bits,變成相乘前兩者都要先右移 16-bit,變成 17.15 乘 17.15,結果是 34.30,實際只存後面的 2.30,再左移 1 位變成 1.31,精確度會差一點。
整數除法如何保留小數?被除數左移 16-bit、除數又移 16-bit?
int Q = a/b; // quotaent
int r = a - b * Q; // remainder
int f = 0;
int p = 0; // 十進位小數位數
while (r) {
r *= 10;
f *= 10;
f += r/b;
p++;
}
int Q = a/b; // quotaent
int r = a - b * Q; // remainder
int f = 0; // fraction
int p; // 二進位小數剩餘位數
for (p = 32; p > 0; p--) {
f <<= 1;
r <<= 1;
q = r/b;
f |= q;
r -= b * q;
}
Saturation:結果大於最大值存成最大值,小於最小值存成最小值。
Overflow:結果超出暫存器範圍,捨棄 MSBs
Truncation 或 Rounding:移除 lower-order bits 減少 precision。
- 無條件捨去
- 四捨五入:中間值進位是 biased rounding
- 四捨六入 convergent rounding:中間值轉成最接近的偶數值是 unbiased rounding。二進位 0.01 少一位是 0.0,0.11 是 1.0
參考
- Blackfin Processor Programming Reference
- GCC 使用 MIPS DSP ASE
- GCC 軟體 fixed-point 函式庫實作 fixed-point fractional 運算,只在特定 target 啟用。_Fract, _Accum, _Sat.
- fixed-point
沒有留言:
張貼留言