Q格式

**Q 格式**是二進制的定點數格式，其中會標示小數位元（也可能包括整數位元）的長度。例如 Q15 數表示分數部份有 15 個位元，而 Q1.14 數表示 1 個整數位元以及 14 個小數位元。

針對有號的定點數，有二種 Q 格式的表示方式。其中一種是將符號位元算在整數位元裡，但另外一種就不是。例如，16 位元的有號整數（無小數位元）可以表示為 Q16.0 或 Q15.0。因此，在用說明 Q 格式的有號定點數字時，可能也需要一併標示總位元數（在此處為 16）。

Q 格式是幾種廣為使用的定點數中的一種。定點數常用在不支援浮點運算器的硬體，或是用在需要固定解析度的應用。

## 特點

Q 格式用來標示定點數，儲存以及運算都是以一般的二進位整數為基礎來處理，因此允許標準的整數硬體／算術邏輯單元來進行有理數運算。程式設計者可以依應用需求，選定其整數位元數、小數位元數（以及資料總位元數），而之後定點數的範圍以及解析度就會依整數位元數、小數位元數而不同。

有些 DSP 架構原生支持一些常用的 Q 格式（例如 Q1.15），這種情形下，可以在一個指令下就進行四則運算，若是加減法，可以支援飽和運算，若是乘除法，可以有正規化的機能。不過大部份的 DSP 無此功能，若 DSP 架構不支持選定的 Q 格式，程式設計者就要自行再針對加減法進行飽和運算，針對乘除法進行正規化。

有號號 Q 格式的表示方式有兩種，都寫成 Q_m_._n_：

* Q 表示這個數字是以 Q 格式表示，在德州儀器則用 Q 表示是有號的 Q 格式（Q 是數學裡表示有理數的字母）
* m.（可省略，若省略的話，假設是 0 或 1）是數字在用二補數表示下的整數位元數，可能包括符位元，也可能不包括（這也是若 m 省略的話，假設是 0 或 1 的原因）。
* n 是數字中小數的位元數，也就是二進位表示時，在小數點右邊的二進位個數（若 n = 0，表示 Q 格式數字是整數）。

一種表示方式將符號位元放在整數位元 _m_ 中一起計算，另一種則不是。確認方式可以將 _m_ 和 _n_ 相加，看是否等於數字位元數，若相等，表示其符號位元放在整數位元 _m_，若比數字位元數少 1，表示其其符號位元獨立計算。

此外，字母 U 可以放在 Q 前面，說明是無號數，例如 UQ1.15，數值範圍是 0.0 to +1.999969482421875 （也就是 $1+{\frac {2^{15}-1}{2^{15}}}$ ）。

有號的 Q 格式數值會用二補數儲存，正如大部份處理器處理整數的情形一樣。在二補數中，會用符號位元填滿沒有用到數字位元。

針對給定的 Q_m_._n_ 格式（假設符號位元也算在 m 個位元內），用 _m_+_n_ 位元的有號整數來處理，再考慮其中有 _n_ 位元是表示小數：

* 其範圍為 $[-(2^{m-1}),2^{m-1}-2^{-n}]$
* 其解析度為 $2^{-n}$

針對給定的 UQ_m_._n_ 格式，用 _m_+_n_ 位元的有號整數來處理，再考慮其中有 _n_ 位元是表示小數：

* 其範圍為 $[0,2^{m}-2^{-n}]$
* 其解析度為 $2^{-n}$

例如 Q15.1 格式的數字：

* 需要位元數為 15+1 = 16 位元
* 其範圍為 [-214, 214 - 2−1] = [-16384.0, +16383.5] = [0x8000, 0x8001 … 0xFFFF, 0x0000, 0x0001 … 0x7FFE, 0x7FFF]
* 其解析度為 2−1 = 0.5

Q 格式和浮點數不同，Q 格式數字的解析度不隨數字大小而不冋。

## 轉換

### 浮點數到 Q 格式

若要將浮點數（例如 IEEE 754）轉換為 Q_m_._n_ 的格式：

1. 將浮點數乘以 2n
2. 四捨五入到最接近的整數

### Q 格式到浮點數

若要將 Q_m_._n_Q 格式的數數轉換為浮點數：

1. 將整數轉換為浮點數
2. 乘以 2−_n_

## 數學運算

Q 格式的數字是二個整數的比例：會儲存分子，而分母固定是 2n。

考慮以下的例子；

* Q8 格式的分母是 28 = 256
* 1.5 等於 384/256
* 會儲存 384，256 不儲存（因為是 Q8 格式，分母固定是 256）

若 Q 格式的基底固定（_n_ 都相同），則 Q 格式的數學運算需維持分母不變。以下是二個相同 Q 格式數字 $N_{1}$ 和 $N_{2}$ 的運算。

$$
{\begin{aligned}{\frac {N_{1}}{d}}+{\frac {N_{2}}{d}}&={\frac {N_{1}+N_{2}}{d}}\\{\frac {N_{1}}{d}}-{\frac {N_{2}}{d}}&={\frac {N_{1}-N_{2}}{d}}\\\left({\frac {N_{1}}{d}}\times {\frac {N_{2}}{d}}\right)\times d&={\frac {N_{1}\times N_{2}}{d}}\\\left({\frac {N_{1}}{d}}/{\frac {N_{2}}{d}}\right)/d&={\frac {N_{1}/N_{2}}{d}}\end{aligned}}
$$

因為分母是二的次冪，因此和二的次冪相乘可以表示為二進制下的左移，和二的次冪相除可以表示為二進制下的右移，很多處理器的左移和右移會比乘除法要快。

為了要維持乘法和除法的精度，中間值需要用雙精度來儲存，在轉換回需要的 Q 格式數字之間，也需要先注意數值修約的處理。

兩個不同 Q 格式基底的數字也可以相乘除，相乘除的數字也可以用另一個基底表示。以下是二個 Q 格式數字 $N_{1}$ （分母 $d_{1}$ ）和 $N_{2}$ （分母 $d_{2}$ ）的運算，運算結果的分母是 $d_{3}$ 。

$$
{\begin{aligned}\left({\frac {N_{1}}{d_{1}}}\times {\frac {N_{2}}{d_{2}}}\right)\times {\frac {d_{1}d_{2}}{d_{3}}}&={\frac {N_{1}\times N_{2}}{d_{3}}}\\\left({\frac {N_{1}}{d_{1}}}/{\frac {N_{2}}{d_{2}}}\right)\times {\frac {d_{1}}{d_{2}d_{3}}}&={\frac {N_{1}/N_{2}}{d_{3}}}\end{aligned}}
$$

 
若用 C 語言，相同 Q 格式基底數字四則運算對應的程式如下（以下的 Q 是表示小數部份的位元數）

### 加法

有飽和

浮點數有 ±Inf，但 Q 格式沒有，若不進行飽和處理，二個很大的正數相加，可能會變成一個很大的負數。若是用組合語言，可以用 Signed Overflow 旗標來避免 C 語言實現時需要的型態轉換。

### 減法

### 乘法

### 除法

## 相關條目

* 二進位標度
* 定點數運算
* 浮點數運算

## 參考資料

## 延伸閱讀

* Oberstar, Erick L. Fixed Point Representation & Fractional Math (PDF). 1.2. Oberstar Consulting. 2007-08-30 [2004] [2017-11-04]. （原始內容存檔 (PDF) 於 2017-11-04）.  (Note: the accuracy of the article is in dispute; see discussion.)

## 外部連結

* Q-Number-Format Java Implementation. [2017-11-04]. （原始內容存檔於 2017-11-04）.