3.9 逐位运算符
逐位运算符是一种比较复杂的运算符,可以分为逐位逻辑运算符(bitwise logical operator)与逐位位移运算符(bitwise shift operator)两种。无论是哪种逐位运算符,都必须先将操作数(要求是整型的操作数)转换成32位的二进制数值,然后再进行运算,运算完毕之后,再将结果转换成十进制数值。
3.9.1 逐位与运算符
逐位与运算符(&)是一个二元运算符,该运算符可以对左右两个操作数逐位执行AND操作,即只有两个操作数中相对应的位都为1时,该结果中的这一位才为1,否则为0。
【实例3.24】请看以下代码,注意加粗的文字。
01 <html> 02 <head> 03 <title>逐位与运算符</title> 04 <script type="text/javascript"> 05 <!-- 06 var x = 9 & 12; 07 document.write(""9 & 12"的结果为:" + x + "<br>"); 08 var y = 1 & 15; 09 document.write(""1 & 15"的结果为:" + y + "<br>"); 10 --> 11 </script> 12 </head> 13 <body> 14 </body> 15 </html>
【代码说明】代码第6行和第8行使用了&运算符。在进行逐位与操作时,逐位与运算符会先将十进制的操作数转换为二进制,再对二进制中的每一位数值逐位进行AND操作,得出结果后,再将结果转换为十进制。其操作方式如下:
十进制 二进制 9 0000 0000 0000 0000 0000 0000 0000 1001 12 0000 0000 0000 0000 0000 0000 0000 1100 --------------------------------------------------- 逐位与操作 8 0000 0000 0000 0000 0000 0000 0000 1000
十进制 二进制 1 0000 0000 0000 0000 0000 0000 0000 0001 15 0000 0000 0000 0000 0000 0000 0000 1111 --------------------------------------------------- 逐位与操作 1 0000 0000 0000 0000 0000 0000 0000 0001
【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample24.htm”里的内容,其运行结果如图3.12所示。
3.9.2 逐位或运算符
逐位或运算符(|)和逐位与运算符类似,可以对左右两个操作数逐位执行OR操作。两个操作数中相对应的位只要有一个为1时,该结果中的这一位就为1,其他情况都为0。
【实例3.25】请看以下代码,注意加粗的文字。
01 <html> 02 <head> 03 <title>逐位或运算符</title> 04 <script type="text/javascript"> 05 <!-- 06 var x = 9 | 12; 07 document.write(""9 | 12"的结果为:" + x + "<br>"); 08 var y = 1 | 15; 09 document.write(""1 | 15"的结果为:" + y + "<br>"); 10 --> 11 </script> 12 </head> 13 <body> 14 </body> 15 </html>
【代码说明】代码第6行和第8行使用了“|”运算符。在进行逐位或操作时,逐位或运算符会先将十进制的操作数转换为二进制,对二进制中的每一位数值逐位进行OR操作,得出结果后,再将结果转换为十进制。其操作方式如下:
十进制 二进制 9 0000 0000 0000 0000 0000 0000 0000 1001 12 0000 0000 0000 0000 0000 0000 0000 1100 --------------------------------------------------- 逐位或操作 13 0000 0000 0000 0000 0000 0000 0000 1101
十进制 二进制 1 0000 0000 0000 0000 0000 0000 0000 0001 15 0000 0000 0000 0000 0000 0000 0000 1111 --------------------------------------------------- 逐位或操作 15 0000 0000 0000 0000 0000 0000 0000 1111
【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample25.htm”里的内容,其运行结果如图3.13所示。
3.9.3 逐位异或运算符
逐位异或运算符(^)和逐位与运算符类似,可以对左右两个操作数逐位执行异或操作。所谓异或操作是指,第1个操作数与第2个操作数相对应的位上两个数值相同时结果为0,否则为1。
【实例3.26】请看以下代码,注意加粗的文字。
01 <html> 02 <head> 03 <title>逐位异或运算符</title> 04 <script type="text/javascript"> 05 <!-- 06 var x = 9 ^ 12; 07 document.write(""9 ^ 12"的结果为:" + x + "<br>"); 08 var y = 1 ^ 15; 09 document.write(""1 ^ 15"的结果为:" + y + "<br>"); 10 --> 11 </script> 12 </head> 13 <body> 14 </body> 15 </html>
【代码说明】代码第6行和第8行使用了^运算符。在进行逐位异或操作时,逐位异或运算符会先将十进制的操作数转换为二进制,对二进制中的每一位数值逐位进行异或操作,得出结果后,再将结果转换为十进制。其操作方式如下:
十进制 二进制 9 0000 0000 0000 0000 0000 0000 0000 1001 12 0000 0000 0000 0000 0000 0000 0000 1100 --------------------------------------------------- 逐位异或操作 5 0000 0000 0000 0000 0000 0000 0000 0101
十进制 二进制 1 0000 0000 0000 0000 0000 0000 0000 0001 15 0000 0000 0000 0000 0000 0000 0000 1111 --------------------------------------------------- 逐位异或操作 14 0000 0000 0000 0000 0000 0000 0000 1110
【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample26.htm”里的内容,其运行结果如图3.14所示。
3.9.4 逐位非运算符
逐位非运算符(~)是一个一元操作符,作用于操作数之前,可以对操作数中所有位的数值取反。在JavaScript中,对一个带符号的整数进行逐位非运算,相当于将该整数改变符号后再减1。
【实例3.27】请看以下代码,注意加粗的文字。
01 <html> 02 <head> 03 <title>逐位非运算符</title> 04 <script type="text/javascript"> 05 <!-- 06 var x = ~12; 07 document.write(""~12"的结果为:" + x + "<br>"); 08 var y = ~-15; 09 document.write(""~-15"的结果为:" + y + "<br>"); 10 --> 11 </script> 12 </head> 13 <body> 14 </body> 15 </html>
【代码说明】代码第6行和第8行使用了“~”运算符。在进行逐位非操作时,逐位非运算符会先将十进制的操作数转换为二进制,对二进制中的每一位数值逐位取反,得出结果后再转换为十进制。其操作方式如下:
十进制 二进制 12 0000 0000 0000 0000 0000 0000 0000 1100 --------------------------------------------------- 逐位非操作 1111 1111 1111 1111 1111 1111 1111 0011 (补码,最高位为1,所以是负数) 1111 1111 1111 1111 1111 1111 1111 0010 (反码) 0000 0000 0000 0000 0000 0000 0000 1101 (绝对值的原码,即13)
十进制 二进制 -15 0000 0000 0000 0000 0000 0000 0000 1111 (绝对值的原码) 1111 1111 1111 1111 1111 1111 1111 0000 (反码) 1111 1111 1111 1111 1111 1111 1111 0001 (补码) -------------------------------------------------- 逐位非操作 14 0000 0000 0000 0000 0000 0000 0000 1110 (补码,最高位为0,所以是正数)
要理解以上的转换过程,必须要掌握二进制的原码、反码和补码这几个概念。
■原码:原码可以分为两个部分,第一部分为二进制的最高位,用于区分正数和负数。如果一个二进制数的最高位为0,则代表正数,如果为1则代表负数。第二部分为数值部分,用二进制的绝对值表示。例如以下代码中,第1行是+0,第2行是-0,第3行是12,第4行是-12。
0000 0000 1000 0000 0000 1100 1000 1100
■反码:对于正数而言,反码等于原码;对于负数而言,反码等于其绝对值的原码并逐位取反。例如以下代码中,第1行是12,第2行是-12。
0000 1100 1111 0011
■补码:对于正数而言,补码等于原码;对于负数而言,补码等于反码加1。例如以下代码中,第1行是12,第2行是-12。
0000 1100 1111 0100
在计算机中,所有二进制都是以补码的形式存放的。
【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample27.htm”里的内容,其运行结果如图3.15所示。
3.9.5 左移运算符
左移运算符(<<)是一个二元操作符,可以将第1个操作数中的所有数值(一共32位)向左移动,移动的位数由第2个操作数决定,因此第2个操作数应该是0~31的整数。
【实例3.28】请看以下代码,注意加粗的文字。
01 <html> 02 <head> 03 <title>左移运算符</title> 04 <script type="text/javascript"> 05 <!-- 06 var x = 12 << 1; 07 document.write(""12 << 1"的结果为:" + x + "<br>"); 08 var y = 15 << 13; 09 document.write(""15 << 13"的结果为:" + y + "<br>"); 10 --> 11 </script> 12 </head> 13 <body> 14 </body> 15 </html>
【代码说明】代码第6行和第8行执行了“<<”运算,在进行左移操作时,左移运算符会先将第1个操作数转换为二进制,再根据第2个操作数来决定左移的位数。如果第2个操作数为1,则第1个操作数所有位数都向左移1位,即第1位变成第2位,第2位变成第3位,以此类推,而第32位则用0来补充。其操作方式如下:
十进制 二进制 12 0000 0000 0000 0000 0000 0000 0000 1100 --------------------------------------------------- 左移操作 24 0000 0000 0000 0000 0000 0000 0001 1000
十进制 二进制 15 0000 0000 0000 0000 0000 0000 0000 1111 --------------------------------------------------- 左移操作 122880 0000 0000 0000 0001 1110 0000 0000 0000
提示
将一个值左移1位,相当于将该数值乘以2;左移2位,相当于将该数值乘以4,以此类推。
【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample28.htm”里的内容,其运行结果如图3.16所示。
3.9.6 带符号的右移运算符
带符号的右移运算符(>>)是一个二元操作符,可以将第1个操作数中的所有数值(一共32位)向右移动,移动的位数由第2个操作数决定,因此第2个操作数应该是范围在0~31的整数。
【实例3.29】请看以下代码,注意加粗的文字。
01 <html> 02 <head> 03 <title>带符号的右移运算符</title> 04 <script type="text/javascript"> 05 <!-- 06 var x = 12 >> 1; 07 document.write(""12 >> 1"的结果为:" + x + "<br>"); 08 var y = -12 >> 1; 09 document.write(""-12 >> 1"的结果为:" + y + "<br>"); 10 --> 11 </script> 12 </head> 13 <body> 14 </body> 15 </html>
【代码说明】代码第6行和第8行执行了“>>”运算,在进行带符号的右移操作时,带符号的右移运算符会先将第1个操作数转换为二进制,再根据第2个操作数来决定右移的位数。如果第1个操作数为1,则第1个操作数所有位数都向右移1位,即第32位变成第31位,第31位变成第30位,以此类推。而第1位的数值补充要由原操作数的符号来决定,如果原操作数是正数,则用0来补充;如果原操作数是负数,则用1来补充。其操作方式如下:
十进制 二进制 12 0000 0000 0000 0000 0000 0000 0000 1100 --------------------------------------------------- 带符号的右移操作 6 0000 0000 0000 0000 0000 0000 0000 0110
十进制 二进制 -12 1111 1111 1111 1111 1111 1111 1111 0100(补码) --------------------------------------------------- 带符号的右移操作 -6 1111 1111 1111 1111 1111 1111 1111 1010(补码)
提示
将一个值带符号右移1位,相当于将该数值除以2(舍丢余数);右移2位,相当于将该数值除以4(舍丢余数),以此类推。
【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample29.htm”里的内容,其运行结果如图3.17所示。
3.9.7 用0补足的右移运算符
用0补足的右移运算符(>>>)与带符号的左移运算符类似,只是在右移时,最左侧的数值都是用0来补充的。
【实例3.30】请看以下代码,注意加粗的文字。
01 <html> 02 <head> 03 <title>用0补足的右移运算符</title> 04 <script type="text/javascript"> 05 <!-- 06 var x = 12 >>> 1; 07 document.write(""12 >>> 1"的结果为:" + x + "<br>"); 08 var y = -12 >>> 1; 09 document.write(""-12 >>> 1"的结果为:" + y + "<br>"); 10 --> 11 </script> 12 </head> 13 <body> 14 </body> 15 </html>
【代码说明】代码第6行和第8行执行了“>>>”运算,在进行用0补足的右移操作时,用0补足的右移运算符会先将第1个操作数转换为二进制,再根据第2个操作数来决定右移的位数。如果第2个操作数为1,则第1个操作数所有位数都向右移1位,即第32位变成第31位,第31位变成第30位,以此类推。而第1位的数值补充永远是0,无论原操作数是正数还是负数。其操作方式如下:
十进制 二进制 12 0000 0000 0000 0000 0000 0000 0000 1100 --------------------------------------------------- 用0补足的右移操作 6 0000 0000 0000 0000 0000 0000 0000 0110
十进制 二进制 -12 1111 1111 1111 1111 1111 1111 1111 0100(补码) ------------------------------------------------------- 用0补足的右移操作 2147483642 0111 1111 1111 1111 1111 1111 1111 1010
【运行效果】以上代码为本书配套代码文件目录“代码\第03章\sample30.htm”里的内容,其运行结果如图3.18所示。