还是从js来讲,由于NHN的树残兄问了个问题:7>>1 是 3 而 -7>>1 是 -4,为啥?
先排除 js 的干扰,ECMAScript 的 9.8.1 ToString Applied to the Number Type 内第三条:
3.If m is less than zero, return the String concatenation of the String "-" and ToString(?m).
这里规定,如果值小于0,这返回 "-" 字符连接 ToString(负的负值)。其实就是‘-‘+ToString(正值)
所以,js 会返回 -111,而实际的负值二进制不是这样的。
实际计算规则是:负数以其正值的补码形式表达。
补码计算规则是:反码+1
反码的计算规则是:正值的二进制表示按位取反。
如上例中 -7 的二进制补码计算顺序为:
1.取正:7
2.取二进制: 0000 0111 (这里按单字节8位二进制表示,当然如果是双字节四字节那就前面的空位都补上0呗)
3.取反码: 1111 1000
4.取补码: 1111 1001
所以 -7 的实际二进制补码表示是 1111 1001
那么二进制补码怎么转为10进制呢?
很简单,逆序步骤就可以了:补码-1变为反码,反码取反变为正值二进制,二进制转十进制,前面加个负号。
看看 -7 >> 1 是怎么运算的:
1. 取得 -7 的二进制补码: 1111 1001
2. 带符号左移1位: 1111 1100
3. 移位后二进制补码-1: 1111 1011
4. 取得反码: 0000 0100
5. 二进制转十进制: 4
6. 补充负号: -4
*[注] 10进制、8进制、16进制以及其它进制类型,只需转换为对应的二进制即可,其它步骤与补码计算一致。
这个问题后来Larry.z 兄也说了下计算方法,但是忘了反码+1变为补码形式。
其后问了下呆呆、雅儒也不知道抓换细节。
因此,记录下来,也便于以后自己复查,好记性不如烂笔头,哎……脑子越来越差了……