【发布时间】:2014-04-12 04:46:25
【问题描述】:
我知道 ~ 是一个按位 NOT 运算符,但是如何将数字上的位反转两次使其像 Math.floor What does ~~ ("double tilde") do in Javascript? 描述了在 Javascript 中使用 Math.floor 与按位运算来舍入数字之间的区别,但我感兴趣的是如何准确地将位反转两次来实现这一点。
谢谢
【问题讨论】:
标签: javascript double
我知道 ~ 是一个按位 NOT 运算符,但是如何将数字上的位反转两次使其像 Math.floor What does ~~ ("double tilde") do in Javascript? 描述了在 Javascript 中使用 Math.floor 与按位运算来舍入数字之间的区别,但我感兴趣的是如何准确地将位反转两次来实现这一点。
谢谢
【问题讨论】:
标签: javascript double
~ 强制将操作数强制转换为整数。解决 Javascript 无法在浮点值和整数值之间进行直接转换的事实是一个技巧。事实上,Javascript 并没有正式的仅整数类型,但实现很可能在内部使用整数来提高性能。
所以~x 是castToInt(x) 的按位倒数。然后你再次反转位得到castToInt(x)。
恰好将浮点数转换为整数的行为几乎类似于Math.floor。最显着的区别是,将四舍五入向零,而Math.floor 向负无穷大舍入。还有一些其他的区别:
js> ~~(-4.5)
-4
js> Math.floor(-4.5)
-5
js> ~~Infinity
0
js> Math.floor(Infinity)
Infinity
js> ~~NaN
0
js> Math.floor(NaN)
NaN
js> Math.floor(1e12)
1000000000000
js> ~~1e12
-727379968 // <- be aware of integer overflows!
【讨论】:
它本质上相当于截断函数(从某种意义上说,它将浮点数转换为整数,正是这样做的),这是 JavaScript 所没有的。这就是为什么负数的行为实际上更接近于Math.ceil。
【讨论】:
来自the spec,按位非,~
- 让
expr成为评估UnaryExpression的结果。- 让
oldValue成为ToInt32(GetValue(expr))。- 将按位补码的结果返回到
oldValue。结果是一个带符号的 32 位整数。
ToInt32here 的定义。
32 位整数i 的“补码”是i XOR 0xFFFFFFFF。
所以把这一切放在一起,你就有了~~i 的含义
ToInt32(i) XOR 0xFFFFFFFF XOR 0xFFFFFFFF
// same as
ToInt32(i) XOR 0x00000000
// same as
ToInt32(i)
请记住负数舍入方向的差异。
我个人更喜欢使用x | 0 而不是~~x,因为它涉及更少的操作以获得相同的结果。
【讨论】: