【JavaScript】~~ で小数の切り捨て(ビット演算子 ~2つで0方向へ切り捨て)
問題
これ、なんですか。この、にょろにょろ。
var y = ~~(x/2);
答え
ビット否定演算子(Bitwise NOT Operator)を2つ~~使うと、小数の切り捨てができる。
>>> ~~(0.8) 0 >>> ~~(1) 1 >>> ~~(1.2) 1 >>> ~~(1.5) 1 >>> ~~(1.9) 1 >>> ~~(123.456) 123
便利なのが、0へ向かって切り捨ててくれるところ(絶対値で切り捨て)。
>>> ~~(-123.456) -123 >>> ~~(-456.789) -456
素直に正負を見て関数を使い分けるとこうなるところ。長くて嫌になりますね。
//xが数値の前提で x = (x > 0) ? Math.floor(x) : Math.ceil(x);
それが、~~なら、ほら!このとおり。
//xは何でもいいですよ♪ x = ~~x;
括弧をつけると、関数っぽいですね。
var y = ~~(x);
もうちょっと細かく
ECMA Scriptの仕様によると、ビット演算するときに、対象をToInt32で32ビット整数にする。
ToInt32の定義は以下のとおり。
9.5 ToInt32: (Signed 32 Bit Integer)
The operator ToInt32 converts its argument to one of 2^32 integer values in the range -2^31 through 2^31-1, inclusive. This operator functions as follows:
1. Call ToNumber on the input argument.
2. If Result(1) is NaN, +0, -0, +∞, or -∞, return +0.
3. Compute sign(Result(1)) * floor(abs(Result(1))).
↑これ。絶対値で切り捨てて、符号はそのまま。
4. Compute Result(3) modulo 2^32 ; that is, a finite integer value k of Number type with positive sign and less than 2^32 in magnitude such the mathematical difference of Result(3) and k is mathematically an integer multiple of 2^32 .
5. If Result(4) is greater than or equal to 2^31 , return Result(4)-2^32 , otherwise return Result(4).
他にも演算させてみるとこのようになる。
~~null; // => 0 ~~undefined; // => 0 ~~0; // => 0 ~~{}; // => 0 ~~[]; // => 0 ~~(1/0); // => 0 ~~false; // => 0 ~~true; // => 1 ~~1.2543; // => 1 ~~4.9; // => 4 ~~(-2.999); // => -2
匿名 2012年4月23日 08:45
x = ~~x;
は
x |= 0;
と書けます
yoshimura 2012年4月23日 09:06
なるほど、変数に入っているときは、その手もありますね。
ビット演算子 |(OR)すると、ToInt32されて、相手が0だから値は変わらない。
エーテル水槽 2012年4月24日 05:24
32ビット整数にしちゃってるので、正しく切り捨てられる数には限界があったりするみたいです。
javascript:alert( ~~999999999.9999999999999 ); //1000000000
javascript:alert( ~~9999999999.9999999999999 ); //1410065408
なので、最大値を考慮して使わないと危険です。
匿名 2012年4月25日 01:03
Math.roundでいいんじゃ…
fflo 2012年5月6日 07:13
関数使う場合は parseInt ですね。