V站上看到的一個提問,有關C#和js的位運算不一致,實際上就是採用的右移不同。
C/C++語言中邏輯右移和算數右移共享同一個運算符>>
。編譯器決定使用邏輯右移還是算數右移,根據的是運算數的類型。如果運算數類型是unsigned
則採用邏輯右移,而signed
則採用算數右移。對於signed
類型的數據,如果需要使用算數右移,或者unsigned
類型的數據需要使用邏輯右移,都需要進行類型轉換。
#include <stdio.h>
2
3 int main(){
4 int a = 3233857544;
5 unsigned int b = 3233857544;
6 printf("%d\n", a);
7 printf("%u\n", b);
8 printf("a >> -171: %d\n", a>>-171);
9 printf("b >> -171: %u\n", b>>-171);
10 printf("a >> 21: %d\n", a>>21);
11 printf("b >> 21: %u\n", b>>21);
12 return 0;
13 }
RESULT
-1061109752
3233857544
a >> -171: -506
b >> -171: 1542
a >> 21: -506
b >> 21: 1542
其中位移量爲負數
求 M>>a (a<0)
- 找到 n(n>=1), 令 2(n-1)<|a|<=2n
- 令 b=2^n - |a|
- b = b mod 32(32 是 M 的位數,也有可能 64,由M類型決定)
- 則 M>>a == M>>b
比如 3233857544>>-171
找到比 171 大的第一個 2^n,是 256
256-171=85
85 mod 32 = 21
所以 3233857544>>-171 == 3233857544>>21