JavaScript的位运算符为什么可以取整呢?取整的原理是什么呢?
比如 12.334 << 0 得出的结果是12,请问为什么呢?
位操作符用于在最基本的层次上,即按内存中表示数值的位来操作数值。ECMAScript 中的所有数
值都以 IEEE-754 64 位格式存储,但位操作符并不直接操作 64 位的值。而是先将 64 位的值转换成 32 位
的整数,然后执行操作,最后再将结果转换回 64 位。对于开发人员来说,由于 64 位存储格式是透明的,
因此整个过程就像是只存在 32 位的整数一样
位运算 的操作数都会先对其进行抽象的 ToInt32 操作
ToUint32: (Unsigned 32 Bit Integer)
1.Let number be the result of calling ToNumber on the input argument.
2.If number is NaN, +0, −0, +∞, or −∞, return +0.
3.Let posInt be sign(number) × floor(abs(number)).
4.Let int32bit be posInt modulo 232; that is, a finite integer value k of Number type with positive sign and less than 232 in magnitude such that the mathematical difference of posInt and k is mathematically an integer multiple of 232.
5.Return int32bit.
三四步就是个求整取余数的过程
<<0 对实际的值没有进行具体的位移操作,但是仍然会进行其中的 ToInt32 操作,在一定的范围内就是简单的按绝对值取整,超出这个范围就会变成意想不到的值
因为javascript的位运算符只对32位整数有效,所以在进行位运算的时候会把运算符两边的数进行强制转换成32位的整数,所以对小数进行位运算会变成整数。12.334 << 0表达式两边取整之后就相当于12<<0,因此位运算符可以取整,不过只限32位,超过32位就会出错。
看代码:
12.334.toString(2);//"1100.010101011000000100000110001001001101110100101111" //转为二进制
所以 12.334 << 0 相当于 二进制 1100 向左移送0位 ;
parseInt('1100',2) //12
这个涉及到JavaScript对位运算符的处理。我们要知道,js中数值都是IEEE 764标准,但标准中规定<<
、>>
、~
等位运算符会对仅为32位的数值定义,所有会有一个ToInt32
的抽象操作,即32位有符号整数。<< 0
表明位移为零,所有就截断了小数部分。下面的也可以:
~~12.334
参考:you dont konw js
you dont know js
对于使用位运算是否有副作用,在知乎这里有讨论
我的看法是,使用位运算符有点geek,但语义化并不清楚。
10 回答11.1k 阅读
6 回答3k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.6k 阅读✓ 已解决
3 回答2.3k 阅读✓ 已解决
3 回答2.1k 阅读✓ 已解决
位运算符用于对
二进制位
进行计算,这些位运算符直接处理每一个比特位(bit),所以是非常底层的运算,好处是速度极快
,缺点是很不直观,许多场合不能使用它们
。位运算符只对
整数
起作用,如果一个运算子不是整数,会自动转为整数后再执行。虽然在JavaScript内部,数值都是以64位浮点数的形式储存,但是做位运算的时候,是以32位带符号的整数
进行运算的,并且返回值也是一个32位带符号的整数
。回到上面的问题:
这是
左移运算符
,左移运算符表示将一个数的二进制值向左移动指定的位数,尾部补0,即乘以2的指定次方(最高位即符号位不参与移动)。左移
0
位,就相当于将该数值转为32位整数,等同于取整,对于正数和负数都有效。