Upgrade to Pro — share decks privately, control downloads, hide ads and more …

BigInt あれこれ / overview about BigInt

BigInt あれこれ / overview about BigInt

Node学園 30時限目の発表資料です
https://nodejs.connpass.com/event/83639/

shimataro

April 27, 2018
Tweet

More Decks by shimataro

Other Decks in Technology

Transcript

  1. BIGINT あれこれ
    BIGINT あれこれ
    (2018/04/27)
    (2018/04/27)
    小田島 太郎 / @shimataro
    NODE学園 30時限目
    NODE学園 30時限目

    View Slide

  2. 自己紹介
    自己紹介
    ウェブリオ株式会社所属(京都)
    サーバサイドエンジニア
    趣味は手品
    前回も参加しました:
    小田島 太郎
    [email protected]
    [email protected]
    [email protected]
    dynamic import あれこれ

    View Slide

  3. この発表について
    この発表について
    対象: Number型じゃ物足りない人
    技術レベル: 初級〜中級
    ↓スライドはこちら↓
    https://speakerdeck.com/shimataro
    https://shimataro.github.io/slides/

    View Slide

  4. 目次
    目次
    背景
    さっそく使ってみる
    速度検証
    Numberとの速度比較
    本番環境で使うには?
    まとめ

    View Slide

  5. 始める前に
    始める前に

    View Slide

  6. 【慶】NODE学園 30回【祝】
    【慶】NODE学園 30回【祝】
    今後も盛り上げていきましょう!

    View Slide

  7. 【慶】4/25 NODE.JS V10リリース【賀】
    【慶】4/25 NODE.JS V10リリース【賀】

    View Slide

  8. 【拝】4/20 関西NODE学園 開校【賀】
    【拝】4/20 関西NODE学園 開校【賀】
    お互い盛り上げていきましょう!

    View Slide

  9. それでは始めます
    それでは始めます

    View Slide

  10. 背景
    背景

    View Slide

  11. 背景
    背景
    Number型
    64bit(ただし 整数部は53bitまで )
    9007199254740991 (約9千兆)が限界
    もっと大きな整数を扱いたい!
    全世界の負債総額は 2京円以上 だってさ
    TwitterのIDも53bitでは表現しきれない
    時代は64bit
    DBにも64bit整数とかあるよね

    View Slide

  12. 背景
    背景
    BigInt 登場!
    現在はStage3
    Node v10 でサポート
    ただし --harmony-bigint が必要
    64bitではなく 任意精度
    https://tc39.github.io/proposal-bigint/

    View Slide

  13. さっそく使ってみる
    さっそく使ってみる

    View Slide

  14. さっそく使ってみる
    さっそく使ってみる
    まずはビルド
    正式リリースされたから公式ページからインストール!
    $ git clone --depth 1 https://github.com/nodejs/node.git
    $ cd node
    $ ./configure
    $ make -j4 # 並列ジョブ数はCPUのコア数に合わせる
    $ ./node -v # バージョン確認!
    v10.0.0-pre
    https://nodejs.org/

    View Slide

  15. さっそく使ってみる
    さっそく使ってみる
    BigIntの生成
    100n, 0x100n
    BigInt(100), BigInt("100"), BigInt("0x100")
    型変換: Number(100n), 100n.toString()
    小数点以下は切り捨てられる: (1n / 2n) === 0n
    Number型との共演はNG
    ビットシフトすら 1n << 10n と書く
    文字列結合は "a" + 1n でOK

    View Slide

  16. 速度検証
    速度検証

    View Slide

  17. 速度検証
    速度検証
    現在最大の (2^77232917 - 1)
    超速い!
    メルセンヌ素数
    $ time node --harmony-bigint -e "2n ** 77232917n - 1n"
    real 0m0.110s ←0.11秒!!
    user 0m0.094s
    sys 0m0.016s

    View Slide

  18. 速度検証
    速度検証
    底を変えてみる
    $ time node --harmony-bigint -e "3n ** 77232917n - 1n"
    real 124m47.252s ←2時間!?
    user 124m43.277s
    sys 0m0.260s
    $ time node --harmony-bigint -e "4n ** 77232917n - 1n"
    real 0m0.161s ←0.16秒!
    user 0m0.132s
    sys 0m0.029s

    View Slide

  19. 速度検証
    速度検証
    10進文字列に変換してみる
    16進文字列に変換してみる
    $ time node --harmony-bigint -e "(2n ** 77232917n - 1n).toString(
    real 473m33.712s ←8時間!!
    user 473m32.767s
    sys 0m0.208s
    $ time node --harmony-bigint -e "(2n ** 77232917n - 1n).toString(
    real 0m0.165s ←0.16秒!
    user 0m0.125s
    sys 0m0.040s

    View Slide

  20. 速度検証
    速度検証
    結果
    2進数で簡単に計算できるものは速い
    2の累乗、4の累乗
    16進文字列への変換
    逆に、2進数で時間がかかるものは遅い
    3の累乗
    10進文字列への変換
    考察: 内部的には2進数ベースで計算している?
    (考察じゃなくてソース読めよ…)

    View Slide

  21. NUMBER型との速度比較
    NUMBER型との速度比較

    View Slide

  22. NUMBER型との速度比較
    NUMBER型との速度比較
    雑なベンチマーク
    let i, j, k, val;
    for(i = 1; i <= 100; i++) {
    for(j = 1; j <= 100; j++) {
    for(k = 1; k <= 100; k++) {
    for(l = 1; l <= 100; l++) {
    val = i;
    val += j;
    val *= k;
    val %= l;
    }
    }
    }
    }

    View Slide

  23. NUMBER型との速度比較
    NUMBER型との速度比較
    Number
    BigInt(数値に n を追加)
    Number型で収まる範囲の演算でも、BigIntだと遅い
    ⇒Numberを使えるなら使ったほうがいい
    real 0m0.381s ←0.38秒
    user 0m0.352s
    sys 0m0.029s
    real 0m22.087s ←22秒!
    user 0m24.116s
    sys 0m0.355s

    View Slide

  24. 本番環境で使うには?
    本番環境で使うには?

    View Slide

  25. 本番環境で使うには?
    本番環境で使うには?
    本番環境ではLTSを使いたい
    10月まで待つ?
    本番環境は --harmony とかあまり使いたくない
    v12まで待つ?
    v12のLTSリリースは来年の10月?
    待ってられん!

    View Slide

  26. 本番環境で使うには?
    本番環境で使うには?
    Babelはどうよ
    https://babeljs.io/blog/2017/09/12/planning-for-
    7.0#stage-3-bigint-new-un nished

    View Slide

  27. 本番環境で使うには?
    本番環境で使うには?
    多分こういうこと
    ↓バベるとこうなる(多分)↓
    全部の演算子を置き換えなきゃアカン
    a += b; // a, bがBigInt型かどうかわからない
    class BigInt { ... } // ラップ用のクラス
    if (typeof a === "BigInt") {
    a = a.plus(b);
    } else {
    a += b;
    }

    View Slide

  28. 本番環境で使うには?
    本番環境で使うには?
    今はまだ big-integer パッケージを使おう
    10進数ベースの演算
    10000000 単位でパックしている
    意外と速い
    $ npm i -S big-integer
    const BigInteger = require("big-integer");
    // "150"
    const strValue = BigInteger(100)
    .plus(50)
    .toString();

    View Slide

  29. まとめ
    まとめ
    Node v10で BigInt に対応したよ
    ただし --harmony-bigint が必要だよ
    2進表現で高速に計算できるものは速いよ
    Numberよりはかなり遅いよ
    現時点では big-integer を使おう
    関西Node学園もよろしく!
    登壇者大募集!
    手品に興味があったら声をかけてね!

    View Slide

  30. ありがとうございました
    ありがとうございました

    View Slide

  31. おまけ
    おまけ
    ここまで見てくれてありがとう( *´艸`)

    View Slide

  32. BIGINT VS BIG-INTEGER 2番勝負
    BIGINT VS BIG-INTEGER 2番勝負

    View Slide

  33. ROUND 1: 雑ベンチ再び
    ROUND 1: 雑ベンチ再び
    big-integer版
    const BigInteger = require("big-integer");
    let i, j, k, val;
    for(i = 1; i <= 100; i++) {
    for(j = 1; j <= 100; j++) {
    for(k = 1; k <= 100; k++) {
    for(l = 1; l <= 100; l++) {
    val = BigInteger(i);
    val = val.plus(j);
    val = val.multiply(k);
    val = val.mod(l);
    }
    }
    }
    }

    View Slide

  34. ROUND 1: 雑ベンチ再び
    ROUND 1: 雑ベンチ再び
    計測結果
    BigIntの結果(再掲)
    BigIntより速くね?
    実は、big-integerはNumberに収まる範囲の演算はその
    まま計算するので速い
    real 0m7.587s
    user 0m8.001s
    sys 0m0.362s
    real 0m22.087s
    user 0m24.116s
    sys 0m0.355s

    View Slide

  35. ROUND 2: 場外乱闘
    ROUND 2: 場外乱闘
    …というわけで、Number型の範囲外でもう一度挑戦して
    みます。

    View Slide

  36. ROUND 2: 場外乱闘
    ROUND 2: 場外乱闘
    big-integer版
    const BigInteger = require("big-integer");
    let i, j, k, val;
    for(i = 1; i <= 100; i++) {
    for(j = 1; j <= 100; j++) {
    for(k = 1; k <= 100; k++) {
    for(l = 1; l <= 100; l++) {
    val = BigInteger(Number.MAX_SAFE_INTEGER).plus(i)
    val = val.plus(j);
    val = val.multiply(k);
    val = val.mod(l);
    }
    }
    }
    }
    real 0m41.659s
    user 0m42.663s
    sys 0m0.932s

    View Slide

  37. ROUND 2: 場外乱闘
    ROUND 2: 場外乱闘
    BigInt版
    let i, j, k, val;
    for(i = 1n; i <= 100n; i++) {
    for(j = 1n; j <= 100n; j++) {
    for(k = 1n; k <= 100n; k++) {
    for(l = 1n; l <= 100n; l++) {
    val = BigInt(Number.MAX_SAFE_INTEGER) + i;
    val += j;
    val *= k;
    val %= l;
    }
    }
    }
    }
    real 0m30.764s
    user 0m33.004s
    sys 0m0.343s

    View Slide

  38. ROUND 2: 場外乱闘
    ROUND 2: 場外乱闘
    BigIntのほうが1.3倍速かった
    変換と加算が増えてBigIntさんも遅くなったけどね

    View Slide

  39. 結論
    結論
    Numberに収まるときもある場合はbig-integerも検討の
    価値あり
    収まらないことが明確な場合はBigIntのほうがいい

    View Slide

  40. View Slide