2018年3月25日日曜日

【Node.js】64bitの16進文字列→10進文字列

タイトルのとおりです。

もともとはNode.jsでランダムな64bit整数を作りたかったんですが、JavaScriptの数値型では整数は2^53までしかサポートされていないので数値じゃなくて10進文字列で取得しようとしたんです。

別に四則演算を全部やりたいわけではないので、自分で作れるんじゃね?と思いました。


やってみた

ランダムな64bitの16進文字列を作るのは簡単。
SIZEを変えれば128bitでも256bitでもいけます。
const crypto = require("crypto");

const SIZE = 8; // 8バイト(64ビット)ほしい

crypto.randomBytes(SIZE, (err, buf) => {
    if (err !== null) {
        // エラー
        console.error(err);
        return;
    }

    // Buffer -> 16進文字列
    const hexstr = buf.toString("hex");
    console.log(hexstr);
});
で、これを10進文字列に変換するわけですが…

あれ?意外と難しいぞ?

JavaScriptのNumber型で扱える範囲を超えるという前提なので、Number.parseIntは使えません。

32bitずつ整数化してあとでつなげようとしても、結局多倍長の加算や乗算が必要になります🤔

結局


NPMのbig-integerパッケージを使いました。
const crypto = require("crypto");
const BigInteger = require("big-integer");

const SIZE = 8; // 8バイト(64ビット)ほしい

crypto.randomBytes(SIZE, (err, buf) => {
    if (err !== null) {
        // エラー
        console.error(err);
        return;
    }

    // Buffer -> 16進文字列
    const hexstr = buf.toString("hex");
    console.log(hexstr);

    // 16進文字列→10進文字列
    const bigint = BigInteger(hexstr, 16);
    const decstr = bigint.toString();
    console.log(decstr);
});
オーバースペックかもしれないけどとりあえず動いた。めでたしめでたし。

ひらめいた。


このbig-integerを使って、現在53bitまでしか対応していないmaylilyを64bit対応というか任意精度に対応できるかもしれない。

今度やってみよう。

BigIntは?


ところで、JavaScriptの世界ではBigIntがstage3になっているので無事サポートされたら簡単な操作で64bit(以上の)整数を扱えますが、演算全体の速度に影響するという理由でBabel7には含まれていません

0 件のコメント:

コメントを投稿