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