Q表記は、2 進固定小数点数形式のパラメータを指定する方法です。たとえば、Q 表記で で表される数値形式は、Q8.8この形式の固定小数点数には整数部分が 8 ビット、小数部分が 8 ビットあることを意味します。
同じ目的で、 他の表記法も数多く使用されています。
意味
テキサスインスツルメンツ版
テキサスインスツルメンツ[1]によって定義されたQ表記法は、文字Qとそれに続く一対の数字m.nで構成されます。ここで、mは値の整数部分に使用されるビット数、nは小数ビット数です。
デフォルトでは、この表記法は符号付きバイナリ固定小数点形式を表し、スケールされていない整数は2 の補数形式で格納され、ほとんどのバイナリ プロセッサで使用されます。最初のビットは常に値の符号 (1 = 負、0 = 非負) を示し、mパラメータではカウントされません。したがって、使用されるビットの総数wは 1 + m + nです。
例えば、仕様Q3.12は、 w = 16ビットの符号付き2進固定小数点数を記述しており、これは符号ビット、整数部の3ビット、および小数部の12ビットで構成されています。つまり、16ビットの符号付き(2の補数)整数であり、暗黙的にスケーリング係数2 −12で乗算されます。
特に、nが 0 の場合、数値は単なる整数です。m が 0 の場合、符号ビットを除くすべてのビットは小数ビットです。その場合、格納される数値の範囲は -1.0 (含む) から +1.0 (含まない) までになります。
mとドットは省略できます。その場合、値が格納されている変数またはレジスタのサイズから推測されます。したがって、Q12 は任意のビット数の符号付き整数を意味し、暗黙的に 2 −12倍されます。
文字U をQの前に付けて、符号なしの2 進固定小数点形式を表すことができます。たとえば、 UQ1.15 は、暗黙的なスケーリング係数 2 −15を持つ符号なし 16 ビット整数として表される値を表します。この範囲は 0.0 から (2 16 −1)/2 15 = +1.999969482421875 です。
ARM版
Q表記法の変形はARMで使用されている。この変形では、m数値に符号ビットが含まれる。例えば、16ビットの符号付き整数はQ15.0TI変形では表記されるが、 Q16.0ARM変形では表記される。[2] [3]
特徴
Q m . nまたは UQ m . n形式の解像度(連続する値間の差)は常に 2 − nです。表現可能な値の範囲は、使用する表記法によって異なります。
たとえば、Q15.1 形式の数値は 15+1 = 16 ビットを必要とし、解像度は 2 −1 = 0.5 で、表現可能な値の範囲は −2 14 = −16384.0 から +2 14 − 2 −1 = +16383.5 です。16 進数では、負の値の範囲は 0x8000 から 0xFFFF で、負でない値は 0x0000 から 0x7FFF まで続きます。
数学演算
Q 数は 2 つの整数の比です。分子は保存され、分母は2 nに等しくなります。
次の例を考えてみましょう。
- Q8の分母は2 8 = 256です
- 1.5は384/256に等しい
- 384 が格納され、Q8 番号であるため 256 が推測されます。
Q 数の底が維持される場合 ( nは一定)、Q 数の数学演算では分母を一定にする必要があります。次の式は、一般的な Q 数とに対する数学演算を示しています。(上記の例を考えると、は 384、は 256 です。)
分母が 2 の累乗であるため、乗算は左への算術シフトとして実装でき、除算は右への算術シフトとして実装できます。多くのプロセッサでは、シフトは乗算や除算よりも高速です。
精度を維持するために、中間の乗算および除算の結果は倍精度である必要があり、目的の Q 数に変換する前に中間結果を 丸めることに注意する必要があります。
C を使用した場合の演算は次のようになります (ここで、Q は小数部のビット数を指すことに注意してください)。
追加
int16_t q_add ( int16_t a 、int16_t b ) { a + bを返します。}
彩度あり
int16_t q_add_sat ( int16_t a 、int16_t b ) { int16_t結果; int32_t tmp ;
tmp = ( int32_t ) a + ( int32_t ) b ; if ( tmp > 0x7FFF ) tmp = 0x7FFF ; if ( tmp < -1 * 0x8000 ) tmp = -1 * 0x8000 ; result = ( int16_t ) tmp ;
結果を返す; }
浮動小数点 ±Inf とは異なり、飽和結果は固定されておらず、示されている実装では、負の値を正の飽和値 (0x7FFF) に追加すると飽和が解除され、その逆も同様です。アセンブリ言語では、符号付きオーバーフロー フラグを使用して、その C 実装に必要な型キャストを回避できます。
減算
int16_t q_sub ( int16_t a 、int16_t b ) { a - bを返します。}
乗算
// 事前計算された値:
#define K (1 << (Q - 1))
// int16_t の範囲に飽和int16_t sat16 ( int32_t x ) { if ( x > 0x7FFF ) return 0x7FFF ; else if ( x < -0x8000 ) return -0x8000 ; else return ( int16_t ) x ; }
int16_t q_mul ( int16_t a 、int16_t b ) { int16_t結果; int32_t温度;
temp = ( int32_t ) a * ( int32_t ) b ; // 結果の型はオペランドの型です// 丸め; 中央の値は切り上げられますtemp += K ; // 基数で割って結果を飽和させて修正しますresult = sat16 ( temp >> Q );
結果を返す; }
分割
int16_t q_div ( int16_t a , int16_t b ) { /* 事前に基数を乗算します (結果が Q8 形式になるように Q16 にアップスケールします) */ int32_t temp = ( int32_t ) a << Q ; /* 丸め: 中央の値は切り上げられます (負の値の場合は切り下げられます)。 */ /* 最上位ビットを比較するか、つまり if (((temp >> 31) & 1) == ((b >> 15) & 1)) */ if (( temp >= 0 && b >= 0 ) || ( temp < 0 && b < 0 )) { temp += b / 2 ; /* または 1 ビットシフトします、つまり temp += (b >> 1); */ } else { temp -= b / 2 ; /* または 1 ビットシフトします、つまり temp -= (b >> 1); */ }戻り値( int16_t )( temp / b ); }
参照
参考文献
- ^ 「付録 A.2」。TMS320C64x DSP ライブラリ プログラマーズ リファレンス(PDF)。米国テキサス州ダラス: Texas Instruments Incorporated。2003 年 10 月。SPRU565。2022年 12 月 22 日時点のオリジナルからアーカイブ(PDF) 。2022年 12 月 22 日閲覧。(150ページ)
- ^ 「ARM Developer Suite AXD および armsd デバッガ ガイド」。1.2。ARM Limited。2001 [1999]。第 4.7.9 章。AXD > AXD 機能 > データ フォーマット > Q フォーマット。ARM DUI 0066D。2017 年 11 月 4 日のオリジナルからアーカイブ。
- ^ 「第 4.7.9 章 AXD > AXD 機能 > データ フォーマット > Q フォーマット」。RealView Development Suite AXD および armsd デバッガ ガイド(PDF)。3.0。ARM Limited。2006 [1999]。pp. 4–24。ARM DUI 0066G。2017年 11 月 4 日のオリジナルからアーカイブ(PDF) 。
さらに読む
- Oberstar, Erick L. (2007-08-30) [2004]. 「固定小数点表現と分数計算」(PDF) . 1.2. Oberstar Consulting. 2017-11-04 にオリジナル(PDF)からアーカイブ。2017-11-04に取得。(注: 記事の正確性については議論があります。議論を参照してください。)
外部リンク
- 「Q-Number-Format Java 実装」。GitHub 。2017年 11 月 4 日にオリジナルからアーカイブ。2017 年 11 月 4 日に取得。
- 「Qフォーマットコンバータ」。2021年6月25日時点のオリジナルよりアーカイブ。2021年6月25日閲覧。
- 「Q ライブラリ (C 実装)」。GitHub。2024年 3 月 5 日に取得。
