小数点数の量子化

掲示板に投稿したもの

X[0.0 〜 2.0]の値を取る小数点数をY[0 .. 31]の整数型に量子化することを考える。普通に考えるとこうなる。

  1. X が 2.0 を含まない場合
    1. Y = trunc(X * 32 / 2.0)
  2. X が 2.0 を含む場合(Z = X * 31 / 2.0 と置く)
    1. Y = trunc(Z)
    2. Y = trunc(Z + 0.5) *1

X が 2.0 を含まない場合は全く問題ない。しかしそうで無い場合は2-2を使っても

  • 0.0 <= Z < 0.5 → Y = 0
  • 0.5 <= Z < 1.5 → Y = 1
  • 30.5 <= Z <= 31.0 → Y = 31 *2

つまりY=0, 31の場合だけ、とれるZの範囲が半分になってしまう。この場合の量子化を正確に行うのは少し難しい。

改良案1)

  • Z = X * (32 - delta) / 2.0 (deltaは適度に小さい数。Xが整数値ならdelta = 1)
  • Y = trunc(Z)

としてYを計算する方法がある。つまり 0.0 <= X <= 2.0 の値を 0.0 <= Z <= 31.99999... に写像してしまえばいい。

改良案2)
X = 2.0 や Y = 32 の値だけを特別扱いする。つまり、

  • Y = trunc(X * 32 / 2.0)
  • if (Y == 32) Y = 31 or Y -= (Y >= 32) or Y -= (Y >> 5)

としてしまう方法もある。

*1: 1だとXがきっかり2.0のときしかYが31にならないので少し改良

*2: Zの最大値は31のため