コンピュータサイエンスにおいて、スケール係数とは、異なるスケールで数値を表すための乗数として用いられる数値であり、数学における指数と同様の働きをします。スケール係数は、現実世界の数値集合を特定の数値形式に合わせるために異なるスケールで表現する必要がある場合に使用されます。スケール係数を使用すると表現可能な値の範囲は広がりますが、精度も低下するため、特定の計算では丸め誤差が生じます。
用途
アプリケーションでは、プログラミングの利便性や、その数値形式に対してハードウェアが提供する特定の利点のために、特定の数値形式が選択されることがあります。たとえば、初期のプロセッサは、小数値を表す浮動小数点演算をネイティブでサポートしていなかったため、実数値にスケール ファクタを適用することで、実世界の値の表現を整数で格納していました。同様に、ハードウェア演算は固定幅 (データ型に応じて通常 16 ビット、32 ビット、または 64ビット) であるため、スケール ファクタを使用すると、精度は犠牲になりますが、指定したスケール ファクタで手動で乗算または除算することにより、より大きな数値を表現できます。[ 1 ]ハードウェアが小数値をサポートしていなかったため、必然的にこれはソフトウェアで行われました。スケール ファクタは浮動小数点数でも使用され、最も一般的には2 の累乗です。例えば、倍精度形式では、スケーリング係数(2進指数)に11ビット、仮数部に53ビットが割り当てられており、さまざまな精度でさまざまな範囲の数値を表現できるようになり、64ビットで表現できる範囲を超えて表現可能な数値の範囲が拡張されます(ただし、精度は低下します)。[ 2 ]
精度が失われる例として、16ビットの符号なし整数(uint16 )は、65,535 10までの値しか保持できません。符号なし16ビット整数を使用して0から131,070 10までの値を表す場合、スケール係数1 ⁄ 2が導入され、スケールされた値は現実世界の偶数整数と正確に一致します。その結果、たとえば、格納された1は現実世界の2を表し、格納された2は現実世界の4を表すため、数値3は表現できません。この表現では、このエラーを回避するのに十分なビットがありません。
スケール値に対する操作
実数値のスケール表現が保存されると、その値が「現実世界」に戻される必要があるまで、スケーリングは多くの場合無視されます。例えば、 2つのスケーリングされた値を加算することは、値をスケーリングせずに実数値を加算し、その結果をスケーリングすることと同等に有効であり、前者の方がはるかに簡単で高速です。ただし、どちらの方法でも、加算された2つの数値は同じスケーリングでなければなりません。[ 3 ]他の演算では、スケーリングが非常に重要です。
例えば、乗算では、両方の数値がスケール化されていることを考慮する必要があります。例として、2つの実世界の値AとBを考えてみましょう。これらの実世界の値の 乗算は、次のように表されます。
A * B = P
代わりにスケール係数Zで表現し、これらのスケール表現を後で乗算すると、結果は次のようになります。
AZ * BZ = Q
AZはAのスケールされた実世界値、つまりA * Zの積であり、同様にBZはBのスケールされた表現です。スケールされた乗算の後、答えはPZと書きません。これは、 PZに格納されている値が答えではないためです。これは、以下の文を並べ替えることで確認できます。各行は等価です。
AZ * BZ = Q A * Z * B * Z = Q (A * B) * Z * Z = Q P * Z * Z = Q PZ * Z = Q
4 行目では、P がA * Bに置き換えられます。したがって、AZ * BZの結果( Q ) はPZではなく 、PZ * Zになります。PZ が答えである場合は、加算や減算の場合と同様に、スケール係数が組み込まれているため、直接格納できます。 ただし、乗算の場合は、2 つのスケールされた値の積に追加のスケーリングが組み込まれています。 これを考慮する限り、演算を実行する前にAZとBZ をAとBに変換する必要はありません。結果をZで割ってから、戻して格納する必要があります。 この後、PZが乗算の結果として格納されますが、これは実際にはAZ * BZの結果 (これもスケールされています)ではなく、A * Bの結果 (目的の答え) のスケールされた表現です。
一般的なスケーリングシナリオ
小数値を整数にスケーリング
前述のように、多くの古いプロセッサ (およびおそらく一部の最新プロセッサ) は、分数演算をネイティブでサポートしていません。この場合、小数値を必要な小数精度の 10 乗で乗算することにより、整数にスケーリングできます。言い換えると、小数点の右側のn桁を保持するには、数全体に10 nを乗算する必要があります。2 進数で計算を実行するコンピュータでは、 2 進小数点の右側のm桁を保持するには、実数に 2 mを乗算します。または、値をm桁左にビットシフトすることもできます。たとえば、次の実際の分数値のセットでは、すべて小数点の右側に 3 桁があります。
15.400、0.133、4.650、1.000、8.001
すべての情報を保存するには(言い換えれば、精度を失わないようにするには)、これらの数値を 10 3 (1,000) 倍して、次の整数値を得る必要があります。
15400, 133, 4650, 1000, 8001
スケールされた数値の値のため、8 ビットの整数で保存することはできません。少なくとも 14 の符号なしビット、より現実的には 16 の符号なしビットが必要になります。
整数値を分数に変換する
特定のプロセッサ、特に組み込みシステム業界で一般的なDSPには、 Q 形式やIQ形式などの固定小数点演算のサポートが組み込まれています。
数値の小数部はフィールドのビットをいくつか占有するため、固定小数点値で可能な値の範囲は、同じビット数の整数で可能な範囲よりも狭くなります。[ 4 ]たとえば、8 ビット フィールドでは、符号なし整数は [0, 255] の値を格納できますが、小数部に 5 ビットが割り当てられた符号なし固定小数点では、整数値に 3 ビットしか残らないため、整数値は [0, 7] しか格納できません。 (2 つのフィールドに格納できる異なる値の数は 2 8 = 256 で同じです。これは、固定小数点フィールドでは整数値ごとに 32 個の小数値も格納できるためです。) そのため、固定小数点形式の最大値よりも大きい可能性がある実際の値を格納するために、スケーリング係数が使用されるのが一般的です。
たとえば、符号なし 8 ビット固定小数点形式 (整数ビット 4 個と小数ビット 4 個) を使用する場合、表現できる最大の整数値は 15 で、表現できる最大の混合値は 15.9375 (0xF.F または 1111.1111 b ) です。必要な実世界の値が [0,160] の範囲にある場合は、この固定小数点表現に収まるようにスケーリングする必要があります。ここでは、スケール係数1 ⁄ 10は使用できません。160 を1 ⁄ 10でスケーリングすると16 になり、この固定小数点形式で格納できる最大値より大きいためです。ただし、最大のスケーリング値160 ⁄ 11 = 14. 54がこの範囲内に収まるため、スケール係数1 ⁄ 11は機能します。次のセットがあるとします。
154、101、54、3、0、160
これらをスケール係数1 ⁄ 11でスケーリングすると、次の値が得られます。
154/11 = 14 101/11 = 9.1818... 54/11 = 4.9090... 3/11 = 0.2727... 0/11 = 0 160/11 = 14.5454...
これらの値の多くは循環小数点を含んでいるため切り捨てられていますが、これは選択されたスケール係数(11 分の 1 は小数点で終わらない)から来ています。これらを固定小数点形式で保存すると、いくらか精度が失われます(元の整数の正確な値とは対照的です)。これはまた、8 ビット形式は 256 の異なる値を保存できますが、このセットの数値は 161 個の可能な値(0 から 160)の範囲からのものなので、問題となります。結局のところ、問題はスケール係数1 ⁄ 11にあり、これにより不必要な精度要件と丸め誤差(実数値を最も近い表現可能な値で近似する場合)が発生しました。[ 5 ]この問題を回避または解決するには、より適切なスケール係数を選択する必要があります。
スケール係数の選択
上記の例は、特定のスケール係数が不要な精度の低下や丸め誤差を引き起こす可能性があることを示しており、適切なスケール係数を選択することの重要性を強調しています。スケール係数1 ⁄ 11を使用してバイナリ表現に変換すると、次の値が得られます。
154/11 = 14 = 1110.0 101/11 = 9.1818... = 1001.00101110... 54/11 = 4.9090... = 100.111010... 3/11 = 0.2727... = 0.010010... 0/11 = 0 = 0.0 160/11 = 14.5454... = 1110.10010...
いくつかの2進小数部は、設定された固定小数点形式で提供される4つの小数ビットよりも多くのビットを必要とします(これは、11分の1も2進数で終了しないためです)。フィールド(4つの整数ビットと4つの小数ビット)に収まるように、残りのビットを切り捨てて、次の格納表現を得ることができます。
1110.0000 1001.0010 0100.1110 0000.0100 0000.0000 1110.1001
または 10 進数で:
14.0 9.125 4.875 0.25 0.0 14.5625
これらが現実世界に呼び戻される際、スケール係数1 ⁄ 11で割られます。これは元のスケーリングの逆数であり、以下の「現実世界」の値が得られます。
154.0 100.375 53.625 2.75 0 160.1875
これらの値は、元の値(スケールダウンしてこの8ビット表現に合わせる前の値)と等しくありません。最も顕著な点は、すべてが整数ではなくなったことです。これは、スケーリング係数の選択ミスにより、ストレージにエラーが発生したことをすぐに示しています。
より良いスケール係数の選択
ほとんどのデータセットは完璧なスケール係数を持つわけではありません。スケーリング処理によって何らかの誤差が生じる可能性が高いからです。しかし、より適切なスケール係数を選択できる場合もあります。理想的なスケール係数は最小値ではなく、可能な限り精度を維持する値である可能性があります。
数を 2 の累乗で割ることは、2 の累乗ごとにすべてのビットを 1 回右にシフトすることと同じです。(これは、10 の累乗で乗算または除算するときに、すべての 10 進数字をそれぞれ左または右にシフトすることと 2 進数で等価です。) ビット パターンは変更されず、2 進指数に等しい桁数だけ移動します (たとえば、8 で割る場合は 2 3 = 3 右に移動します)。一方、2 進数で 2 の累乗の整数ではない数で割ると、ビット パターンが変わります。これにより、2 進小数点の右側に多くのビットを持つビット パターンが生成され、必要な精度が不自然に導入される可能性があります。これは、小数部の分母が 2 の累乗ではない場合に特に当てはまります。2の累乗の逆数ではない分数はすべて2 進数で繰り返されるためです。[ 6 ]したがって、ほとんどの場合、スケール ファクターとして 2 の累乗を使用するのが適切です。切り捨ての結果、フィールドの端からずれたビットが失われる可能性は依然としてありますが、これにより、不正確な(丸め誤差のため)または切り捨てられた新しいビットが導入されることが回避されます。 [ 6 ]
スケール係数に2の累乗を使用する例として、上記のデータセットに1 ⁄ 16のスケール係数を適用できます。元のデータセットのバイナリ値は以下の通りです。
154 = 1001 1010 101 = 0110 0101 54 = 0011 0110 3 = 0000 0011 0 = 0000 0000 160 = 1010 0000
これらはすべて0から255までの整数なので、8ビットで正確に表現できます。これらを1/16でスケーリングすることは、 16で割ることと同じであり、ビットを4つ右にシフトすることと同じです。この場合、スケーリングは各数値の最初の4ビットと最後の4ビットの間に2進小数点を挿入することによって行われます。これは、この表現の所定の形式と一致します。したがって、これらの数値はすべて整数として表現するのに8ビット以上を必要としないため、スケーリングして固定小数点形式で保存するのにも8ビット以上は必要ありません。
参照
参考文献
- ^リンツ & ワン 2003、12–13 ページ。
- ^リンツ & ワン 2003、14–15 ページ。
- ^イェーツ 2013、6ページ。
- ^イェーツ 2013、4~5頁。
- ^リンツ&ワン 2003、18ページ。
- ^ a b「2進分数」 . Floating-point-gui.de . 2020年7月6日閲覧。
- Yates, R. (2013). 「固定小数点演算:入門」(PDF) . Digital Signal Labs. 2015年9月12日時点のオリジナルよりアーカイブ(PDF) 。
- Linz, P.; Wang, RLC (2003). 『数値計算手法の探求:MATLABを用いた科学計算入門』Jones and Bartlett Publishers . ISBN 0-7637-1499-2。