首页 > js 中的 ~~ 这种语法来自哪里,使用的时候跟Math.floor() 效果是一样的

js 中的 ~~ 这种语法来自哪里,使用的时候跟Math.floor() 效果是一样的


// var sec = ~~ ( new Date().getTime() );
// 抱歉之前给的例子不太恰当,应该是如下的例子
var sec = ~~ ( ( end_time - new Date().getTime() ) ) / 1000 );


符号类型转换


最近在看阮兄的 《Javascript标准参考教程》的运算符 一章时, 看到了关于这个问题的解释,自己再搬过来回答一下.

否运算计算时将算子转成32位整数再运算, 即:
~3.1 === ~3
~ -4.1 === ~ -4

另外, 整数两次否运算与与算子是相等的, 即:
~~ 3 === 3
~~ -3 === -3

所以, 结合这两点的逻辑, 就可以达到取整的目的

以上


首先解释下为什么 ~~ 可以达到 Math.floor() 类似的效果:
关于 ~(位取反),我们可以从 ECMAScript 了解到它的算法,注意到第二步,再进行位取反前,需要先将数值进行 ToInt32 运算,而在 ToInt32 里,有一个 sign(number) * floor(abs(number))——这是取整的操作。
因此用 ~~ 来取整,实际是用 ToInt32 时的取整操作,类似的其他操作(如 num >> 0)也一样。

但这些操作也有一个很大的问题,就是当需要取整的数超过 32 位里,操作会得到一个错误的值,因为在 ToInt32 里除了取整操作,还把 数值 % 2<sup>32</sup>(转成 32 位数值)。
~~17179869222.23042 == 38(正确取整后的值应该是 17179869222)

从题主给出的代码:var sec = ~~ ( new Date().getTime() );,有两个问题,一是 .getTime() 就已经是整数了,不需要转了;二是 .getTime() 的值已经超过 32 位整数了,所以转换出来值是不正确的。


~按位非运算符,位于整型参数之前,它将所有操作位取反。相当于改变运算数的符号并减去1。

由于操作数不一定是整数,所以要进行数据类型转换。
~可以简单理解为下面的表达式:

var oper = ~2;
var oper = (-fn(2)) - 1;

function fn(num) {
    return isNaN(parseInt(num, 10)) ? -1 : parseInt(num, 10);
}

~~:

var oper = ~~2;
var oper = fn(2);

function fn(num) {
    return isNaN(parseInt(num, 10)) ? -1 : parseInt(num, 10);

parseInt在做类型转换的时候会根据操作数向下或者向上取整。
操作数是小于0的浮点数,向上取整。
操作数是大于0的浮点数,向下取整。


Math.floor()还是不一样的 ,实际上等效于

function trunc(x) {
    return x < 0 ? Math.ceil(x) : Math.floor(x);
}

~做的操作是按位取反,两次取反又会变回原操作数
但是当操作数是小数的时候,会忽略其小数部分

~~43.2 == ~(~43.2) == ~(~43) == ~ ~43 == (~ ~)43 == 43
~~-43.2 == ~(~-43.2) == ~(~-43) == ~ ~-43 == (~ ~)-43 == -43

Math.floor(-43.2) == -44

RTFM

http://php.net/manual/en/language.operators.bitwise.php

【热门文章】
【热门文章】