JavaScriptで小数を整数にするマニアックな方法とその実行速度
JavaScript を使って小数を整数に変換する(小数部分のカット)いろいろな方法の紹介です。Math.random() を利用するときによく使うでしょうか。最も一般的な方法は Math.floor() を使うものだと思うのですが、他の方法でも出来るので紹介してみます。
ついでに実行速度まで計測してみました。
「切り捨て」のみに着目しています。「切り上げ」や「四捨五入」はまた別の方法になりますのでご注意ください。
Math.floor(number)
Math.floor(5.368) //→ 5一番使われる有名な方法です。
ただしこの方法は、「プラス値」であれば「小数部分のカット」になるのですが、数値が「マイナス値」だった場合は挙動が違いますので注意してください。
Math.floor(-5.368) //→ -6つまり、Math.floor() は「値を切り下げる」ということです。その数を超えない最も大きな数値を返します。
parseInt(number)
parseInt(5.368) //→ 5文字列「"18px"」を数値「18」にと単位を取り除きたい時に使われる parseInt() も小数を整数に変換します。
Math.floor() と異なり parseInt() は「切り下げ」ではなく、単純に「小数部分のカット」の挙動となるので注意してください。
parseInt(-5.368) //→ -5~~number
~~5.368 //→ 5ここからはマニアックな方法ですね。何故こうなるとか詳しい話はわかっておりませんが、ビット演算の過程で小数部分が落ちるようです。しっかり5になります。
値がマイナス値だった場合は、「小数部分のカット」の値を返します。Math.floor() とは挙動が異なります。
~~(-5.368) //→ -5~~ は「文字列」を「数値」にも自動で変換してくれるので、例えば
~~"5.368" //→ 5(数値)の「文字列」である数値も数値に変換して小数部分をカットしてくれます。~~ を使うことで小数部分がない整数文字列であれば「整数文字列」⇒「整数数値」の変換が可能だということになりますね。
number|0
5.368|0 //→ 5同じく小数部分のカットをしてくれます。
マイナス値の挙動は ~~ と同様です。
-5.368|0 //→ -5~~ と同じく「文字列」を「数値」に変換します。
"5.368"|0 //→ 5(数値)number>>0
5.368>>0 //→ 5同じですね。「0」の部分の数値を変更すると出力される値が変わりますが、いまいち理由はわかりません・・・
また、マイナス値の挙動は ~~ と同様です。
-5.368>>0 //→ -5同じく「文字列」を「数値」に変換します。
"5.368"|0 //→ 5(数値)number^0
5.368^0 //→ 50乗しているので数学的にいえば「1」となるはずなのですが、JS上では小数部分が切り取られます。浮動小数点数というところからこういう現象が起こるのでしょうか。よくわかっていません・・・
マイナス値の挙動は ~~ と同様です。
-5.368^0 //→ -5同様に「文字列」を「数値」に変換します。
"5.368"^0 //→ 5(数値)まだ他にも方法はありそうですが、このぐらいにしておきます。
実行速度
次に上の変換方法での実行速度を計測します。上記の変換方法で1秒あたりの変換回数を計測しました。ブラウザによる差異も考慮して、Windows の最新版 Firefox と最新版 GoogleChrome でそれぞれ計測します。
プラス値の小数を整数に変換する場合を計測します。
Firefox
| 変換方法 | 1秒あたりに変換回数 |
|---|---|
| Math.floor(number) | 641,056,436 回/秒 |
| parseInt(number) | 32,989,067 回/秒 |
| ~~number | 647,903,051 回/秒 |
| number|0 | 649,466,645 回/秒 |
| number>>0 | 650,667,320 回/秒 |
| number^0 | 651,250,090 回/秒 |
GoogleChrome
| 変換方法 | 1秒あたりに変換回数 |
|---|---|
| Math.floor(number) | 319,980,755 回/秒 |
| parseInt(number) | 37,321,886 回/秒 |
| ~~number | 322,548,311 回/秒 |
| number|0 | 324,040,173 回/秒 |
| number>>0 | 323,019,525 回/秒 |
| number^0 | 324,002,731 回/秒 |
結果考察
まず、Firefox と GoogleChrome でだいぶ結果が違いますが、環境にもよると思うのでそこの違いは割愛します。ただ、parseInt(number) だけは他の5種類と比べてだいぶ結果が劣ります。単位を取るという作業が入る分遅いようです。
Math.floor(number) に関しては昔は遅いブラウザが多かったように感じますが、今は高速化されています。特に意識すること無く Math.floor を使ってしまっても問題ないということですね。
「マイナス値であろうと小数点以下カット」をしたい場合は、parseInt() ではなく、他の ~~ 等で変換したほうが速度的、文字数的には良いということになりました。ただし、見慣れない表記ではあるので「ご利用は計画的に」ということでしょうか。