あいつの日誌β

働きながら旅しています。

丸めたい時に使うティップス

あらすじ

他人が書いている javascript のコードを見てたらチルダの使い方が面白かったので紹介します。

~(チルダ)についておさらい

~ ってbit反転するアレなんだけど javasciript だとたまにこんな記述があるので覚えておくと良いです。

if ( ~['a', 'b', 'c'].indexOf('b')  ) { 
    console.log('exist');
}

以下と同等です。

if ( ['a', 'b', 'c'].indexOf('b') !== -1 ) { 
    console.log('exist');
}

DeNADev / Arctic.js を眺めていた

そしたら以下のような記述があるんですよ。

x = ~~(x * scale);

なんとなく Math.Round の代用をしている様にも見える

console.log( ~~(10.1) ); // 10
console.log( ~~(10.9) ); // 10

Math.Round vs hack

こんなのとか http://www.slideshare.net/madrobby/extreme-javascript-performance

こんなのとか http://jsperf.com/math-round-vs-hack/48

結論

まあサーバーサイドエンジニアであんまりここがボトルネックになることないので気にしなくてもいいんじゃないかなあ。

一応以下のようにベンチとったけど。とりあえず~~はなんとなく Math.ceil やらを書いた時にこういった書き方もあるんだっけなあとか思い出してもいいんじゃないっすかね。

// !node-bench %
// run many times so that we can abstract out the overhead of promise creation.
//exports.countPerLap = count;
exports.compare = {
    MathRound: function(done) {

        var somenum = -500 + (Math.random() * 1000);
        var rounded = Math.round(somenum);
        done();
    },
    hack: function(done) {

        var somenum = -500 + (Math.random() * 1000);
        var rounded = ~~(somenum);
        done();
    }
};

結果

Please be patient.
Scores: (bigger is better)

hack
Raw:
 > 629.7572427572428
 > 635.9070929070929
 > 648.3326673326674
 > 632.924075924076
 > 604.005994005994
Average (mean) 630.1854145854147

MathRound
Raw:
 > 554.048951048951
 > 562.027972027972
 > 545.2057942057942
 > 541.2377622377622
 > 462.27172827172825
Average (mean) 532.9584415584416

Winner: hack
Compared with next highest (MathRound), it's:
15.43% faster
1.18 times as fast
0.07 order(s) of magnitude faster