购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

5.2 位运算符

JavaScript定义了7个位运算符,它们可以分为两类。

☑ 逻辑位运算符:位与(&)、位或(|)、位异或(^)和位非(~)。

☑ 移位运算符:左移(<<)、右移(>>)和无符号右移(>>>)。

5.2.1 位运算概述

位运算就是对二进制数进行的计算。

位运算是整数的逐位运算。例如,1+1=2,这在十进制计算中是正确的;但是在二进制计算中,1+1= 10;而对于二进制数100取反,则就等于001,而不是-100。

在JavaScript中,位运算要求运算数必须是32位的整数,如果位运算数是非整型,或者大于32位的整数,则将返回NaN。

在默认情况下,所有整数都是带有符号的整数。带有符号的整数中,第1~31位表示整数的值,第32位表示整数的符号,0表示正数,1表示负数。因此整数值的范围为-2147483648~2147483647。

对于正整数来说,它以二进制形式进行存储,第1~31位中每一位都表示2的幂,序数从0开始。第1位表示2 0 ,第2位表示2 1 ,第3位表示2 2 ,依此类推。对于没有用到的位使用0来进行填充。例如,对于十进制数值12,使用二进制表示法如图5-3所示。

图5-3 12的二进制表示法

其中第1~4位为有效位,如果使用如下方法返回对应的二进制值,可以看到返回值仅是有效位,其他数位由于并不重要,因此就没有返回。

     alert((12).toString(2));                //返回二进制值1100

实际上利用有效位,对于二进制值1100,可以很轻松地使用如下方法转换为十进制值:

     (23*1)+(22*1)+(21*0)+(20*0)
     =8+4+0+0
    =12

对于负数来说,二进制的存储方式一般采用二进制补码的方式来实现:

第1步,先计算负数对应的正数的二进制值。例如,对于-12,则先计算12的二进制值,如图5-3所示。

第2步,对第一步中计算的二进制值进行反码。所谓反码就是把位值逐位取反。例如,0取反为1,1取反为0。针对图5-3所示的12的二进制值反码之后,则如图5-4所示。

图5-4 12的二进制值反码

第3步,为二进制反码值加1,如图5-5所示。

图5-5 为二进制值反码加1

第4步,最终,-12的二进制值为:11111111111111111111111111110100。

但是如果使用如下方法返回-12的二进制值:

     alert((-12).toString(2));                //返回值-1100

则返回值不是11111111111111111111111111110100,而是-1100,即使用数字绝对值的二进制值加上负号的形式返回。

在处理带有符号的整数时,JavaScript是不允许访问第32位符号位的值。

对于无符号的整数来说,第32位不再是符号位,而是用来表示值,所以它的数值范围为0~4294967295。如果数值小于等于214783647的整数来说,无符号整数与有符号整数表示是一样的,而大于214783647的整数,则第32位为1,此时与有符号整数表示是不一样的。当然,JavaScript所有数值默认都是带有符号位的,只有数值参与到位运算之后,才能生成无符号的整数。

5.2.2 逻辑位运算

逻辑位运算符与逻辑运算符的运算方式相同,但是针对的对象不同。逻辑位运算符针对的是二进制的整数值,而逻辑运算符针对的是非二进制的其他类型数据。

&运算符(位与)表示布尔AND操作。它对二进制值逐位进行比较,并根据表5-2所示的换算表返回结果。

表5-2 &运算符

【示例1】 12和5进行位与运算,则返回值为4。

     alert(12&5);                //返回值4

如图5-6所示以算式的形式解析12和5进行位与运算的过程。通过位与运算,只有第3位的值为全true,故返回true,其他位均返回false。

图5-6 12和5进行位与运算

提示: 在位运算中数值1表示true,0表示false,反之亦然。

|运算符(位或)表示布尔OR操作。位或运算将根据表5-3所示的换算表返回结果。

表5-3 |运算符

【示例2】 12和5进行位或运算,则返回值为13。

     alert(12|5);               //返回值13

如图5-7所示以算式的形式解析12和5进行位或运算的过程。通过位或运算,只有第2位的值为false外,其他位均返回true。

图5-7 12和5进行位或运算

^运算符(位异或)表示布尔XOR操作。位异或运算将根据表5-4所示的换算表返回结果。

表5-4 ^运算符

【示例3】 12和5进行位异或运算,则返回值为9。

     alert(12^5);                    //返回值9

如图5-8所示以算式的形式解析12和5进行位异或运算的过程。通过位异或运算,第1、4位的值为true,而第2、4位的值为false。

图5-8 12和5进行位异或运算

~运算符(位非)表示布尔NOT操作。位非运算将根据3步操作进行处理:

第1步,把运算数转换为32位的二进制整数。

第2步,逐位反码,即逐位进行取反操作。

第3步,把二进制反码转换为十进制浮点数。

【示例4】 对12进行位非运算,则返回值为-13。

     alert(~12);                  //返回值-13

如图5-9所示以算式的形式解析对12进行位非运算的过程。

图5-9 对12进行位非运算

位非运算本质上就是对数字进行求负运算,然后再减1。因此,使用如下方法也可以获得相同的结果。

     ~12=-12-1;

如果使用如下语句则可以检测它们是否相等:

     alert(~12 == -12-1);                  //返回true

5.2.3 移位运算

移位运算就是对二进制值进行有规律移位,移位运算可以设计很多奇妙的效果,这在图形图像编程中应用比较广泛。

【示例1】 把数字5向左移动2位,则返回值为20。

     alert(5<<2);                    //返回值20

如果用算式图进行演示则如图5-10所示。

图5-10 把5向左移位2位运算

在移位运算过程中,右侧空出的位置,JavaScript自动使用0进行填充,确保整个值是一个完整的32位二进制值。在左移操作中,符号位始终保持不变。在移位过程中,如果超出32位的值将自动被丢弃。

右移运算包含有符号和无符号两种形式。有符号右移运算与左移运算操作相反,它把32位数字中的所有有效位整体右移。移位后的空位位于有效位的左侧,但是位于符号位的右侧,此时JavaScript会使用符号位的值来填充空位。移动过程中超出的值将被自动丢弃。

【示例2】 把数值1000向右移8位,则返回值为3。

     alert(1000>>8);                  //返回值3

如果用算式图进行演示则如图5-11所示。

图5-11 把1000向右移位8位运算

【示例3】 把数值-1000向右移8位,则返回值为-4。

     alert(-1000>>8);                //返回值-4

如果用算式图进行演示则如图5-12所示。可以看到当符号位值为1时,则有效位左侧的空位全部使用1进行填充。

对于无符号右移,可以使用>>>运算符来表示,它将无符号的32位整数所有数位整体右移。对于无符号或正数右移运算,则无符号右移与有符号右移运算的结果是相同的。

图5-12 把-1000向右移位8位运算

【示例4】 下面两行表达式的返回值都是相同的。

【示例5】 对于负数来说,无符号右移将使用0来填充所有的空位,同时会把负数看作正数来处理。所以所得的结果一般都会非常大。

如果用算式图进行演示则如图5-13所示。左侧的空位就不再用符号位的值来填充,而是用0来填充。

图5-13 把-1000向右无符号移位8位运算

在执行运算时,JavaScript会把这个数值转换为无符号的等价形式,尽管第32位是一个符号位,但是此时会把它看作一个数值位进行运算。所以,在使用无符号右移运算符时,要特别小心,避免出现意想不到的错误。 uuHwNK4xjTS4bYysj3BXE2HLYk0A6dJBbm6+FOBsJKMLiCIh3zzNZQcvq1iM0Sm6

点击中间区域
呼出菜单
上一章
目录
下一章
×