ユユユユユ

webエンジニアです

算術右シフトを正しく丸めるためにバイアスを加算する

 マシンがどのように乗算・除算を最適化するについて。二の累乗による乗算は左シフト演算を用いて行うことができる。同じように、二の累乗による除算は右シフト演算を用いで行うことができる。符号なし数であれば論理右シフトを用いるし、二の補数(符号あり数)であれば算術右シフトを使う。

 非負整数に対する算術右シフトは、とりもなおさず論理右シフトを意味するので深く考える必要はない。例えば x = 12340 とおくと、下図のように、結果は切り下げられる。

k x>>k (binary) x>>k (decimal) x/2k
0 0011000000110100 12340 12340.0
1 0001100000011010 6170 6170.0
4 0000001100000011 771 771.25
8 0000000000110000 48 48.203125

 同じように、 x = -12340 とおいて、負数について算術右シフトを適用すると、こちらも同じく切り下げられる。

k x>>k (binary) x>>k (decimal) x/2k
0 1100111111001100 -12340 -12340.0
1 1110011111100110 -6170 -6170.0
4 1111110011111100 -772 -771.25
8 1111111111001111 -49 -48.203125

 しかしこれは求められる動作ではない。というのは、整数の除算は常に0に丸めたいからである。つまり、正数であれば切り下げ、負数であれば切り上げる。いずれも0の方向に丸める。

 無策に算術右シフトを実施すると、一様に切り下げが実施される。これは0方向に丸める要件を満たさないので、戦略が必要である。

 とはいえ、なんのことはない。算術右シフトの計算対象が負数のときは、除算に先立って 除数 - 1 をバイアスとしてあらかじめ加算すればよいだけの話である。ここでいうと (2^k) - 1 をあらかじめ加算してから、割る。整数一般について、除算の結果を切り上げるテクニックと変わらない。

k bias x + bias (x+bias)>>k (binary) (x+bias)>>k (decimal) x/2k
0 0 1100111111001100 1100111111001100 -12340 -12340.0
1 1 1100111111001101 1110011111100110 -6170 -6170.0
4 15 1100111111011011 1111110011111101 -771 -771.25
8 255 1101000011001011 1111111111010000 -48 -48.203125