位操作符
- 因为位操作符在数值都表示的最底层的操作,因此性能上比其他操作符要好,只做了解,性能好,但是会导致代码可读性降低
- 二进制
- 二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”,由18世纪德国数理哲学大师莱布尼兹发现。当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的。计算机中的二进制则是一个非常微小的开关,用“开”来表示1,“关”来表示0。数字计算机只能识别0和1。简单,易于电子方式的实现。
- 十进制转二进制
- 用十进制数字除以2,取余数,用得到的结果继续除以2,一直到1除以2,然后求倒序就是二进制了
- 例如:10,10/2 = 5 余 0 ;5/2 = 2余1;2/2 = 0;这时候除尽了,则进行最后一次计算,1/2除不开,直接等于1即可;最后组合余数为:0101,然后倒序就是1010,因此10转为二进制就是1010了
- 因此,9的二进制就是9/2=4余1,4/2=2余0,2/2=0余0,1/2余1,得1001,倒序9的2进制就是1001
- 39的二进制就是:39/2=19余1,19/2=9余1,9/2=4余1,4/2=2余0,2/2=0余0,1/2余1,组合余数:111001,倒序,39的二进制就是100111
- 高位补0
- 在内存中某一个类型的值是有固定长度的,比如int类型的是32位的,10转为二进制位1010,那么就会在1010前面补28个0,补为32位进行存储
- 一般正数高位补0,负数高位补1
- 二进制转十进制
- 按权相加法
- 10的二进制是1010,从右往左按下标来数,0的下标是0,1为1,0为2,1为3,把这些二进制中数字是1的下标当做2的幂进行相加,那么1010 = 0 + 2^1 + 0 + 2^3 = 0 + 2 + 0 + 8 = 10
- 9的二进制是1001,相应的1001 = 2^0 + 0 + 0 + 2^3 = 1 + 0 + 0 + 8 = 9
- 39的二进制是100111,相应的100111 = 2^0 + 2^1 + 2^2 + 0 + 0 + 2^5 = 1 + 2 + 4 + 0 + 0 + 32 = 39
- 符号位
- 正负号标记
- 负十进制转二进制
- 以-10为例,先将整数部分进行二进制计算,余数为0101,倒序10的二进制为1010,高位补0补到8位得00001010,取反得到11110101然后加1,由于二进制中只有0和1,因此遇2要进一位,则-10转为二进制位-11110110,负数高位补1
- 二进制负数转十进制
- 以-10为例,负数二进制位11110110,先减1,0位不够减,向前借一位,0往前借一位,得2,2减1得1,因此得到11110101,然后取反得到-00001010,这就是10的二级制了
- 小数转二进制
- 小数点前面按照正负数转换即可,把小数点前面的正数部分剥离开,补0,小数点后面的,每次乘以2,得到的结果取正数部分即可,然后拼接一起
- 例如:10.2,10转为二进制为1010,剥离整数部分补0为0.2,0.2乘以2,为0.4,取整数部分0,0.4乘以2,得0.8,取整数部分0,0.8乘以2,得1.6,取整数部分1,现在整数部分有1了,记录1,然后剥离出去,这个1不用转二进制,即使转也是1,然后留下0.6,继续乘以2,得到1.2,剥离,得0.2,乘以2,得0.4,取整数部分……一直到够32位或者到达指定位数或者小数部分为0,最终结果为:1010.00110011001100110011
- 例如:10.5,10转二进制为1010,保留剥离,剩余0.5,0.5乘以2得1.0,取整数部分,小数部分为0,因此不需要继续计算了,所以10.5转为二进制结果为:1010.1
- 二进制小数转十进制
- 先把整数部分和小数部分拆来,例如10.5的二进制为1010.1,拆为1010和0.1,然后整数部分按照二进制转十进制正常转换,小数部分0.1 =1 乘以 2 ^ -1 = 0.5,拼接后的10.5
- 例如:10.2转为二进制位1010.00110011001100110011,整数部分转为10,小数部分为0.00110011001100110011就等于:0 * 2^ -1 + 0 * 2^-2 + 1 * 2^-3 + 1 * 2^ -4 + 0 * 2^-5…… (对应小数位置的0或1) * 2 ^ -n(从左往右1 - n)
- 位操作是程序设计中对位模式按位或二进制数的一元和二元操作
- 在js中对64位(0-9 + a-z + A-Z + - + ~)的数值会转为32位数值,计算完成在转为64位,NaN和Infinity会被当做0来处理,这是由于转换时存在的副效应,如果使用位操作符转换非数字,则会先把其转为Number类型,再进行转换
- 按位非
- 用~表示
- 10的二进制位1010,补32位为00000000000000000000000000001010
- var num = ~10,表示非10的二进制,则对上面的32位二进制数字进行求反得:11111111111111111111111111110101
- 因此var num = ~10得 -11,本质上是对操作数的负值-1,相等于var num2 = -num - 1;
- 按位与
- 用&表示
- 先将两边的操作数转为二进制,然后补齐32位,每一位进行比较,遇0返回0,都为1返回1
- 例:2 & 4,2转为二进制为10,补齐00000000000000000000000000000010,4转为二进制为100,补齐后为:00000000000000000000000000000100,每一位对应比较,按照上面规则,没有对应的,全返会0,因此结果为00000000000000000000000000000000,也就是0
- 例2 & 3,2转二进制为10,补齐00000000000000000000000000000010,3转二进制为11,补齐后得到结果为:00000000000000000000000000000011,参照以上规则,1对应1返回1,有0返回0,则得到结果为:00000000000000000000000000000010,转为十进制后,结果就为2
- 按位或
- 用|表示
- 先将两边的操作数转为二进制,然后补齐32位,每一位进行比较,遇1返回1,都为0返回0
- 例:2 | 4,2转为二进制为10,补齐00000000000000000000000000000010,4转为二进制为100,补齐后为:00000000000000000000000000000100,每一位对应比较,按照上面规则,遇1返回1,因此结果为00000000000000000000000000000110,也就是十进制的6
- 例2 | 3,2转二进制为10,补齐00000000000000000000000000000010,3转二进制为11,补齐后得到结果为:00000000000000000000000000000011,参照以上规则,遇1返回1,都为0返回0,则得到结果为:00000000000000000000000000000011,转为十进制后,结果就为3
- 按位异或
- 用^表示
- 先将两边的操作数转为二进制,然后补齐32位,每一位进行比较,一个为1,一个为0返回1,都为1返回0,都为0返回0
- 例:2 ^ 4,2转为二进制为10,补齐00000000000000000000000000000010,4转为二进制为100,补齐后为:00000000000000000000000000000100,每一位对应比较,按照上面规则,因此结果为00000000000000000000000000000110,也就是十进制的6
- 例2 ^ 3,2转二进制为10,补齐00000000000000000000000000000010,3转二进制为11,补齐后得到结果为:00000000000000000000000000000011,参照以上规则,则得到结果为:00000000000000000000000000000001,转为十进制后,结果就为1
- 左移
- 由<<表示
- 就是将十进制的数转为二进制,将整体向左移动多少位后产生的结果
- 例如:var result = 2 << 5; 2转为二进制为10,补位后为00000000000000000000000000000010,向左移动5位,得00000000000000000000000001000000,左移会把空位以0进行填充,然后把此结果转为十进制得64;
- 有符号右移
- 由>>表示
- 例如:var result = 2 >> 5; 2转为二进制为10,补位后为00000000000000000000000001000000,向左移动5位,得00000000000000000000000000000010,然后把此结果转为十进制得2;
- 无符号右移
- 由>>>表示
- 会对32位都进行向右移动
- 例如: var result = 2 >> 5; 2转为二进制为10,补位后为00000000000000000000000001000000,向左移动5位,得00000000000000000000000000000010,然后把此结果转为十进制得2;但是负数结果就不一样了,只做了解
- 位操作符应用
- 例如:var str = 'abcd'; var result = ~str.indexOf('a'); // -1 ; var result = ~str.indexOf('e'); // 0
网友评论