not good but great

プログラミング、アート、映画・本の感想について書きます。

チルダ2回でMath.floor()の代用をする

チルダの意味とは

チルダ「~」はビット反転演算子で、整数をビット反転させると反転させて1引いた数になる。

これを説明する前に2進数における、補数や符号付き整数について説明する。

以下はこれを参考にしている。
2の補数を理解する (1) - とあるソフトウェア開発者のブログ

1の補数

1の補数とは次の条件を満たす数。

「X」の2進数と「Xの1の補数」の2進数を足すと、全てのビットが1になる。

・例
Xの2進表現(8bit):01011100
Xの1の補数:10100011
(01011100 + 10100011 = 11111111)

「Xの1の補数」は「Xの2進表現」をビット反転させたものである。

2の補数

2の補数とは次の条件を満たす数。

「X」の2進数と「Xの1の補数」の2進数を足すと、2のn乗になる。(nはXのビット数)

・例
Xの2進表現(8bit):01011100
Xの2の補数:10100100
(01011100 + 10100100 = 100000000 = 2の8乗)

「2の補数」は「ビット反転+1」で計算できる。

符号付き整数

符号付き整数を表現するためには2の補数を利用する。

ルール
・最上位ビットが1のときは負の数、0のときは0または生の数
・負の数は、絶対値の2進表現の2の補数

2進表現 10進表現(符号無し) 10進表現(符号付き)
1111 15 -1
1110 14 -2
1101 13 -3
1100 12 -4
1011 11 -5
1010 10 -6
1001 9 -7
1000 8 -8
0111 7 7
0110 6 6
0101 5 5
0100 4 4
0011 3 3
0010 2 2
0001 1 1
0000 0 0

チルダでビット反転

バイナリー(2の補数) 値(10進数)
5 00000000 00000000 00000000 00000101 5
~5 11111111 11111111 11111111 11111010 -6

定義通り5にチルダをつけると、ビット反転させて1引いた数になっている。
・参考
http://msdn.microsoft.com/ja-jp/library/ie/zf9s465t(v=vs.94).aspx

チルダを2回使う

仕様書を見ると、チルダを使った場合、32bitのInt型になるので、小数点が切り捨てられるらしい。だからチルダを2回使うと、実質小数点以下切り捨てになる。
Math.floorと同じ働きをするわけだ。

ビット演算で小数点切り捨て - NullPointer's

var pi = {
        normal: Math.PI,
        tilda: ~Math.PI,
        doubleTilda: ~~Math.PI
};

console.log(pi.normal);//3.141592653589793 
console.log(pi.tilda);//-4
console.log(pi.doubleTilda);//3

parseIntとの違い

小数をint型にするのとは何が違うのかという投稿を見つけた。
javascript - ~~ vs parseInt? - Stack Overflow

parseIntは文字列を数値に変換で来たり、32bitに制限されないらしい。難しいのでよくわからない。

ダブルチルダの良いところを回答者はこう述べる。

It's usually faster than calling a method.
It's faster to type than anything else.
It makes power users feel cool because it's sort of inscrutable and also sort of justifiable. :)

簡単に書けて、早いということか。javascriptに精通してなかったらわかりにくいというデメリットはあると思う。