マシンがどのように乗算・除算を最適化するについて。二の累乗による乗算は左シフト演算を用いて行うことができる。同じように、二の累乗による除算は右シフト演算を用いで行うことができる。符号なし数であれば論理右シフトを用いるし、二の補数(符号あり数)であれば算術右シフトを使う。
非負整数に対する算術右シフトは、とりもなおさず論理右シフトを意味するので深く考える必要はない。例えば x = 12340 とおくと、下図のように、結果は切り下げられる。
k | x»k (binary) | x»k (decimal) | x/2^k |
---|---|---|---|
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/2^k |
---|---|---|---|
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/2^k |
---|---|---|---|---|---|
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 |