pirosikick's diary

君のハートにunshift

~~

かなりコネタ。

今日、spin.jsのソースを読んでいたらなんじゃこりゃ!と思った1行があった。

var end = ~~((args[length]-1)/2);

~~ってなんだよ。

実行してみる

コンソールで実行してみる。

> ~~(1)
1

> ~~(-1)
-1

> ~~(1.555)
1

> ~~(-2.78)
-2

> ~~2.4
2

まぁ何となくわかっていたが小数点切り捨てを行うらしい。

調べてみる

~ってJavascriptでどういう役割だったっけ?と調べてみると、ビット否定演算子だった。で、~~はそれを2回繰り返しているので元の値に戻るはずだが、なぜ小数点切り捨てが発生するのか?

仕組み

11.4.8 ビット否定演算子 (Bitwise NOT Operator) ( ~ )

生成規則 UnaryExpression : ~ UnaryExpression は、次のように評価される:

1. UnaryExpression を評価。
2. GetValue(Result(1)) を呼出す。
3. ToInt32(Result(2)) を呼出す。
4. Result(3) にビット補数を適用する。結果は符号付き 32 ビット整数である。
5. Result(4) を返す。

11 式 (Expressions)

3で32ビットのintに変換されるようです。なので、整数になる模様。

ちなみに

OR演算子(|)やシフト演算子(>>)でもおなじことができる。

> 1111.1111 >> 0
1111

> 12.21232 << 0
12

> 12.321321 | 0
12

が、単項演算子ではないので、~のように関数ぽく実行できない。

まとめ

速度的にはMath.floorとほぼ変わらなかった(10万回実行して10ms位の差)ので~~を使って、ツウぶりましょう。