symmetry half

よく、「半分に割るときはビットシフトを使え」という言葉を耳にする。
 
ところがこのビットシフト、正負に対してシンメトリーになっていない。
 
シンメトリーになっていないことが、不自然だとは思わない。
むしろ、通常の割り算がシンメトリーになっている事実に、驚愕したことさえある。
(昔の開発環境は、その辺がアシンメトリーだったもので)
 
unsigned int u;
 
があるとき、
 
u = (u / 2);
 

 
u = (u >> 1);
 
は同じになる。
 
ところが、
 
signed int s;
 
があるとき、
 
s = (s / 2);
 

 
s = (s >> 1);
 
は同じにならない。
 
では、どうすれば良いのか。
 
signed int k = (s >> (sizeof(s)*8-1)); // k = (s>>31);
s = ((s-k) >> 1);
 
とでもしてやれば良い。
 
と思って、ふと「ハッカーのたのしみ」を読み返してみたら、普通に同じことが書かれていた。