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/

D79a0829d09a325462fc9a1462ec503b?s=128

shimataro

April 27, 2018
Tweet

Transcript

  1. BIGINT あれこれ BIGINT あれこれ (2018/04/27) (2018/04/27) 小田島 太郎 / @shimataro

    NODE学園 30時限目 NODE学園 30時限目
  2. 自己紹介 自己紹介 ウェブリオ株式会社所属(京都) サーバサイドエンジニア 趣味は手品 前回も参加しました: 小田島 太郎 shimataro@GitHub odashima.taro@Facebook

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

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

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

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

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

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

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

  10. 背景 背景

  11. 背景 背景 Number型 64bit(ただし 整数部は53bitまで ) 9007199254740991 (約9千兆)が限界 もっと大きな整数を扱いたい! 全世界の負債総額は

    2京円以上 だってさ TwitterのIDも53bitでは表現しきれない 時代は64bit DBにも64bit整数とかあるよね
  12. 背景 背景 BigInt 登場! 現在はStage3 Node v10 でサポート ただし --harmony-bigint

    が必要 64bitではなく 任意精度 https://tc39.github.io/proposal-bigint/
  13. さっそく使ってみる さっそく使ってみる

  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/
  15. さっそく使ってみる さっそく使ってみる BigIntの生成 100n, 0x100n BigInt(100), BigInt("100"), BigInt("0x100") 型変換: Number(100n),

    100n.toString() 小数点以下は切り捨てられる: (1n / 2n) === 0n Number型との共演はNG ビットシフトすら 1n << 10n と書く 文字列結合は "a" + 1n でOK
  16. 速度検証 速度検証

  17. 速度検証 速度検証 現在最大の (2^77232917 - 1) 超速い! メルセンヌ素数 $ time

    node --harmony-bigint -e "2n ** 77232917n - 1n" real 0m0.110s ←0.11秒!! user 0m0.094s sys 0m0.016s
  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
  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
  20. 速度検証 速度検証 結果 2進数で簡単に計算できるものは速い 2の累乗、4の累乗 16進文字列への変換 逆に、2進数で時間がかかるものは遅い 3の累乗 10進文字列への変換 考察:

    内部的には2進数ベースで計算している? (考察じゃなくてソース読めよ…)
  21. NUMBER型との速度比較 NUMBER型との速度比較

  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; } } } }
  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
  24. 本番環境で使うには? 本番環境で使うには?

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

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

  27. 本番環境で使うには? 本番環境で使うには? 多分こういうこと ↓バベるとこうなる(多分)↓ 全部の演算子を置き換えなきゃアカン a += b; // a,

    bがBigInt型かどうかわからない class BigInt { ... } // ラップ用のクラス if (typeof a === "BigInt") { a = a.plus(b); } else { a += b; }
  28. 本番環境で使うには? 本番環境で使うには? 今はまだ big-integer パッケージを使おう 10進数ベースの演算 10000000 単位でパックしている 意外と速い $

    npm i -S big-integer const BigInteger = require("big-integer"); // "150" const strValue = BigInteger(100) .plus(50) .toString();
  29. まとめ まとめ Node v10で BigInt に対応したよ ただし --harmony-bigint が必要だよ 2進表現で高速に計算できるものは速いよ

    Numberよりはかなり遅いよ 現時点では big-integer を使おう 関西Node学園もよろしく! 登壇者大募集! 手品に興味があったら声をかけてね!
  30. ありがとうございました ありがとうございました

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

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

  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); } } } }
  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
  35. ROUND 2: 場外乱闘 ROUND 2: 場外乱闘 …というわけで、Number型の範囲外でもう一度挑戦して みます。

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

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

  40. None