二进制数与位运算符
位运算符是基于二级制数进行操作的,即表示数字的 32 个数位,它由0和1组成…
二进制数表示整数18
ECMAScript整数有两种类型,即有符号整数(允许用正数和负数)和无符号整数(只允许用正数)。在ECMAScript中,所有整数字面量默认都是有符号整数。
有符号整数使用31位(第0到第30位)表示整数的数值,用第32位(第31位)表示整数的符号,0表示正数,1表示负数。数值范围从-2147483648到2147483647。
前31位中的每一位都表示2的幂,从第1 位(位 0)开始,表示20,第2位(位1)表示21。没用到的位用0填充,即忽略不计。例如,下图展示的是数18的表示法。

18的二进制版本只用了前5位,它们是这个数字的有效位。把数字转换成二进制字符串,就能看到有效位:
var Num = 18;
alert(Num.toString(2)); //输出 "10010"
这段代码只输出”10010”,而不是18的32位表示。其他的数位并不重要,因为仅使用前5位即可确定这个十进制数值。如下图所示:

二级制数表示负数-18
负数也存储为二进制代码,不过采用的形式是二进制补码。计算数字二进制补码的步骤有三步:
1.确定该数字的非负版本的二进制表示(例如,要计算-18的二进制补码,首先要确定18的二进制表示) 2.求得二进制反码,即要把0替换为1,把1替换为0 3.在二进制反码上加1
按照如上步骤计算:
1)获取18的二级制表示
0000 0000 0000 0000 0000 0000 0001 0010
2)求得二进制反码
1111 1111 1111 1111 1111 1111 1110 1101
3)在二进制反码上加1
1111 1111 1111 1111 1111 1111 1110 1101
1
---------------------------------------
1111 1111 1111 1111 1111 1111 1110 1110
因此,-18的二进制表示即1111 1111 1111 1111 1111 1111 1110 1110。记住,在处理有符号整数时,开发者不能访问31位。
特别需要注意的是,把负整数转换成二进制字符串后,ECMAScript并不以二进制补码的形式显示,而是用数字绝对值的标准二进制代码前面加负号的形式输出。例如:
var iNum = -18;
alert(iNum.toString(2)); //输出 "-10010"
这段代码输出的是”-10010”,而非二进制补码,这是为避免访问位31。所有整数字面量都默认存储为有符号整数。只有ECMAScript的位运算符才能创建无符号整数。
二级制数表示小数
现代计算机中,一般都以IEEE 754标准存储浮点数,这个标准的在内存中存储的形式实际上是一种科学计数法 ,用符号,指数和尾数来表示,底数为2,也就是把浮点数表示为尾数乘以2的指数次方再添加上符号的形式。
| 符号位 | 阶码 | 尾数 | 总长度 | |
|---|---|---|---|---|
| float | 1 | 8 | 23 | 32 |
| double | 1 | 11 | 52 | 64 |
浮点数在内存中的是使用科学计数法来表示的,我们先将浮点数用二进制的形式表示出来。
// 整数部分
// 例如12可以表示为
// 2³*1 + 2²*1 + 2¹*0 + 2º*0 = 12
// 8*1 + 4*1 + 2*0 + 1*0 = 12
// 二级制表示为1100
//小数部分
// 例如0.18的小数部分可以表示为
// ½*0 + ¼*0 + ... = 0.18
// 0.5*0 + 0.25*0 + 0.125*1 + 0.0625*0 + 0.03125*1 + ... = 0.18
// 也就是说小数可以表示为2的附一、负二、负三次方...这样的数相加
// 二级制表示为0.001011100001010001111010111000010100011110101110000101
12.18表示为double
1)获取二进制表示
12.18使用二级制表示为1100.001011100001010001111010111000010100011110101110000101。
2)获取科学计数法的表示
double类型尾数为52位,使用科学计数法表示,不足52位补0,超出部分删除,最终结果为1.1000010111000010100011110101110000101000111101011100*2³。
3)计算阶码
double类型阶码共11位,可以表示-1024~1023,因为指数可以为负数,为了方便表示,先加上1023变为非负数,上面的3表示为3+1023=1026,二进制为10000000010。
4)最终结果
符号位,0为正,1为负。所以最终结果是
0 10000000010 1000010111000010100011110101110000101000111101011100
12.18表示为float
1)获取二进制表示
12.18使用二级制表示为1100.001011100001010001111010111000010100011110101110000101。
2)获取科学计数法的表示
float类型尾数为23位,使用科学计数法表示,不足52位补0,超出部分删除,最终结果为1.10000101110000101000111*2³。
3)计算阶码
float类型阶码共8位,表示的范围是-128~127,因为指数可以为负数,为了方便表示,先加上127变为非负数,上面的3表示为3+127=130,二进制为10000010。
4)最终结果
符号位,0为正,1为负。所以最终结果是
0 10000010 10000101110000101000111
二级制与8进制、16进制之间的转换
十进制数由0~9共10个数字字符组成,在十进制数的每一位上满十进一,在十进制每一位中表示最大数字为9.
二进制数由0和1两个数字字符组成,在二进制中“逢二进一”,在二进制每一位中表示最大数字为1.
八进制是由0~7共8个数字字符组成,在八进制中“逢八进一”,在八进制中每一位中表示最大数字为7.
十六进制是由0~9、A、B、C、D、E、F共16个字符组成,在十六进制中“逢十六进一”,在十六进制中最大的数是F。
// 如十进制的123使用二进制、八进制、十六进制表示
// 二进制
// 123 = 64*1 + 32*1 + 16*1 + 8*1 + 4*0 + 2*1 + 1*1
// 1111011
(123).toString(2)
// 八进制
// 123 = 8*8*1 + 8*7 + 1*3
// 173
(123).toString(8)
// 十六进制
// 123 = 16*7 + 1*11
// 7b
(123).toString(16)位运算操作
程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。
1、位运算 NOT(~)
位运算NOT由否定号(~)表示,位运算NOT是三步的处理过程:1)把运算数转换成32位数字2)把二进制数转换成它的二进制反码3)把二进制数转换成浮点数。它实质上是对数字求负,然后减1。
var iNum1 = 25; //25 等于 00000000000000000000000000011001
var iNum2 = ~iNum1; //转换为 11111111111111111111111111100110
alert(iNum2); //输出 "-26"
2、位运算 AND(&)
两个都为1才为1,否则为0。
| 第一个数字中的数位 | 第二个数字中的数位 | 结果 |
|---|---|---|
| 1 | 1 | 1 |
| 1 | 0 | 0 |
| 0 | 1 | 0 |
| 0 | 0 | 0 |
| **3、位运算 OR( | )** |
两个中有一个为1结果就为1,否则为0。
| 第一个数字中的数位 | 第二个数字中的数位 | 结果 |
|---|---|---|
| 1 | 1 | 1 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 0 | 0 | 0 |
4、位运算 XOR(^)
两个中有且仅有一个为1结果就为1,否则为0。
| 第一个数字中的数位 | 第二个数字中的数位 | 结果 |
|---|---|---|
| 1 | 1 | 0 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 0 | 0 | 0 |
位运算常见使用场景
1、判断一个数是奇数还是偶数
利用and运算 & 判断一个数是奇数还是偶数,这是因为二进制的最末位为0表示该数为偶数,最末位为1表示该数为奇数。因此只需要把数和1进行and运算,根据结果就可以判断。
var val = 15;
if(val&1 === 0){
console.log('值为偶数')
}
if(val&1 === 1){
console.log('值为奇数')
}
来自:https://www.kelede.win/posts/二进制数与位运算符/
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!