~ 运算符查看表达式的二进制表示形式的值,并执行位非运算。
Javascript 按位取反运算符 (~) ,对一个表达式执行位非(求非)运算。如 ~1 = -2; ~2 = -3;
js取反我只知道个!,但是~为什么也叫取反,他返回的又不是boolean类型?
~1,~2 的二进制又不是 -2 ,-3 ,怎么会转换成这么奇怪的值?
~ 运算符查看表达式的二进制表示形式的值,并执行位非运算。
Javascript 按位取反运算符 (~) ,对一个表达式执行位非(求非)运算。如 ~1 = -2; ~2 = -3;
js取反我只知道个!,但是~为什么也叫取反,他返回的又不是boolean类型?
~1,~2 的二进制又不是 -2 ,-3 ,怎么会转换成这么奇怪的值?
偶然看到这个问题,挖个坟。
按位取反的运算规则上面那位同学已经说的很好了,我补充三点:
按位取反的运算规则这么奇怪并不是JavaScript独有的,而是所有的计算机语言都是这样的。
这样做的主要原因是为了为了统一减法和加法,在计算机中,减法会变成加一个负数,而负数会以补码的形式存储。而这样主要是因为补码和数字的十进制数有这么转换关系,负数:补码(x) = -x - 1
,正数:补码(x) = x
因为补码是针对负数存在的,那么只要数据类型有无符号数
,就没有这样的烦恼了,比如C语言有无符号整型,就能对无符号整型直接按位取反。
如果没有无符号类型,而且也只是想要按位取反,而不是附带补码的按位取反,需要另外的方法。
让全1的数据和当前数据做按位抑或就行了。比如,你有一个32位的数据a,需要对它做按位取反,那么这样就行了:0xFFFF ^ a
var a = 0x8321;
console.log(a.toString(2));
console.log((0xFFFF ^ a).toString(2));
//1000001100100001
//111110011011110 => 左边最高位是0,被隐藏了。
第一位同学写的挺好的,但一开始我没太明白为什么这样计算?,以下是学习做的笔记。
首先我们先要明白有符号整数,有符号整数的最高位表示的是符号位,0 为正数,1 为负数,例如(为方便理解,使用八位二进制):
// 十进制 => 原码
3 => 00000011
-3 => 10000011
然后是反码,正整数的反码就是它本身(原码),负整数的反码是在其本身的基础上符号位不变,再把其余各位取反。
// 十进制 => 原码 => 反码
3 => 00000011 => 00000011
-3 => 10000011 => 11111100
最后就是补码了,正整数的补码是它的原码,因此正整数的原码、反码、补码都是一样的;负整数的补码是在反码的基础上加 1 得到的。
// 十进制 => 原码 => 反码 => 补码
3 => 00000011 => 00000011 => 00000011
-3 => 10000011 => 11111100 => 11111101
上面这些概念我们理解之后,取反就很好懂了;取反是在补码的基础上进行的,因此取反运算(~n)需要将整数转为补码,之后再取反,最后转换成原码。需要注意的是,正整数的补码取反之后符号位是 1,因此这个取反后的数是一个负整数,我们需要按照负整数计算补码的方式做逆运算得到原码,例如:
3 => 00000011 => 11111100 => 11111011 => 10000100 => -4
// 1. 十进制转换成补码(00000011),需要注意正整数反码和补码是它本身
// 2. 对补码进行取反(11111100)
// 3. 把已经取反的补码转换成反码(11111011),补码转换成反码的公式:反码 = 补码 - 1
// 4. 最后把反码逆运算转换成原码(10000100),逆运算的过程是反码的符号位不变其余各位取反
// 5. 此时,结果就是 -4
负整数取反:
-3 => 10000011 => 11111100 => 11111101 => 00000010 => 2
// 1. 十进制转换成原码(10000011)
// 2. 原码转换成反码(11111100)
// 3. 反码转换成补码(11111101),公式是:补码 = 反码 + 1
// 4. 对反码进行取反(00000010),此时因为取反后的二进制数的符号位为 0,即表明这是一个正整数,上文说过正整数的反码和补码就是它本身,因此最终结果是 2
8 回答4.8k 阅读✓ 已解决
6 回答3.5k 阅读✓ 已解决
5 回答2.9k 阅读✓ 已解决
5 回答6.4k 阅读✓ 已解决
4 回答2.3k 阅读✓ 已解决
4 回答2.8k 阅读✓ 已解决
3 回答2.5k 阅读✓ 已解决
按位取反还真和
boolean
没多大关系,大体流程是这样的:就来看看
~1
的计算步骤:将
1
(这里叫:原码)转二进制 =00000001
按位取反 =
11111110
发现符号位(即最高位)为
1
(表示负数),将除符号位之外的其他数字取反 =10000001
末位加1取其补码 =
10000010
转换回十进制 =
-2
计算步骤就这么奇怪,讨厌,但就是有牛逼的人乐意这么写,让你看不懂代码,以此表示高深莫测,去吧少年,去揍他们^^