-4的二进制表示为1111 1111 1111 1011
成都创新互联公司主要从事成都做网站、网站建设、网页设计、企业做网站、公司建网站等业务。立足成都服务垦利,10年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:18982081108
i3 右移3位,移出的不管,左端补1 变为1111 1111 1111 1111 这是-1的二进制表示,所以结果为-1.
i5 同理。
具体原理:
先来说一下怎么得出负数的二进制。原码,反码,补码,这三个概念搞清。
1、原码:一个正数,按照绝对值大小转换成的二进制数;一个负数按照绝对值大小转换成的二进制数,然后最高位补1,称为原码。
比如 00000000 00000000 00000000 00000101 是 5的 原码。
10000000 00000000 00000000 00000101 是 -5的 原码。
备注:
比如byte类型,用2^8来表示无符号整数的话,是0 - 255了;如果有符号, 最高位表示符号,0为正,1为负,那么,正常的理解就是 -127 至 +127 了.这就是原码了,值得一提的是,原码的弱点,有2个0,即+0和-0(10000000和00000000);还有就是,进行异号相加或同号相减时,比较笨蛋,先要判断2个数的绝对值大小,然后进行加减操作,最后运算结果的符号还要与大的符号相同;于是,反码产生了。
2、反码:正数的反码与原码相同,负数的反码为对该数的原码除符号位外各位取反[每一位取反(除符号位)]。
取反操作指:原为1,得0;原为0,得1。(1变0; 0变1)
比如:正数00000000 00000000 00000000 00000101 的反码还是 00000000 00000000 00000000 00000101
负数10000000 00000000 00000000 00000101 的反码则是 11111111 11111111 11111111 11111010。
反码是相互的,所以也可称:10000000 00000000 00000000 00000101 和 11111111 11111111 11111111 11111010互为反码。
备注:还是有+0和-0,没过多久,反码就成为了过滤产物,也就是,后来补码出现了。
3、补码:正数的补码与原码相同,负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1.
比如:10000000 00000000 00000000 00000101 的补码是:11111111 11111111 11111111 11111010。
那么,补码为:
11111111 11111111 11111111 11111010 + 1 = 11111111 11111111 11111111 11111011
备注:1、从补码求原码的方法跟原码求补码是一样的 ,也可以通过完全逆运算来做,先减一,再取反。
2、补码却规定0没有正负之分
所以,-5 在计算机中表达为:11111111 11111111 11111111 11111011。转换为十六进制:0xFFFFFFFB。
搞懂二进制表示后,再来说一下左移右移运算符。
左移运算是将一个二进制位的操作数按指定移动的位数向左移位,移出位被丢弃,右边的空位一律补0。右移运算是将一个二进制位的操作数按指定移动的位数向右移动,移出位被丢弃,左边移出的空位或者一律补0,或者补符号位,这由不同的机器而定。在使用补码作为机器数的机器中,正数的符号位为0,负数的符号位为1。(均由机器来定)
So,为什么得到-1知道了吧~~~
左移就是将原来的参数所有二进制位向左移动指定的位数,本例中就是移动二位,然后末尾以零补齐。右移正好相反,向右边移动指定位数,然后左边以零补齐。
教你个简单的计算方法,以本例来说,左移就是将原数乘以2的2次方(4)。右移就是原数除以2的2次方(4)。就是最后的结果。
当然实现的方法是比较多的,这里给出一种:
//arr循环左移times次
function shiftArr(arr, times){
times = times%(arr.length);//考虑times大于等于length的情况
return arr.slice(times).concat(arr.slice(0, times));
//取出两个子数组然后连接
}
其他的思路有删除arr前若干个元素并添加到其末尾等(参考Array对象的方法)。
如有问题欢迎继续交流!
不是java任何语言都没有, 位运算中左移跟符号没有关系的, 因为最高位就是符号位
例如8位的byte中最高位如果是 1那就表示负数 如果是左移一位, 那么最高位就会丢掉, 最低位补0 1111 1111 1 就会变成 1111 1110