とてつもない巨大な整数を扱いたい場合。
JavaScriptには BigInt というのが用意されてます。
これを使って数学問題でよくみかける・・・
- 2の100乗を7で割った余り、
- 3の100乗を5で割った余り、
などを合同式を使わず求めるコード例を紹介!
数学的な解き方ではないですが、
BigIntの実用的な例としてメモしておきます。
このページの目次
BigIntとは何か?無限に近い巨大整数を表せる
まずJavaScriptにおける BigInt について。
一般的に整数は 253 - 1 までしか表せません。
でも BigInt だとそれ以上の数を扱うことが可能です。
▼ MDNでのBigIntの解説
BigInt は組み込みオブジェクトで、 Number プリミティブで表現できる最大の数、 2^53 - 1 よりも大きな数値を信頼できるものとして表現する方法を提供します。 BigInt は任意に巨大な整数に使用することができます。
説明の通り「任意の巨大な整数」に利用可能。
宣言のやり方は主に次の2通りです。
▼ 数値の後に n をつけて宣言
1 2 |
var bi1 = 9007199254740991n; var bi2 = 0x1fffffffffffffn; |
▼ BigInt() に文字列で整数を渡して宣言
1 2 |
var bi1 = BigInt("9007199254740991"); var bi2 = BigInt("0x1fffffffffffff"); |
このコードみたく、BigIntでは new が不要みたいです。
ただし1つ要注意なことがあります。
それは使える演算子に制限があること
次の説明の通り、対応してるのは6種類+αだけです。
▼ MDNでのBigIntで使える演算子の解説
BigInt (または Object でラップした BigInt) を利用することができる演算子は、 +, *, -, **, % です。ビット操作演算子は、同様に利用できますが、 >>> (論理的右シフト) は BigInt が常に符号付きなので除きます。
/ 演算子もすべての数値に対して、期待される通りに動作します。ただ BigInt はBigDecimal ではないため、演算結果は 0 の方向に丸められます。別の言い方をすれば、小数を返すことはありません。
とどのつまり、使えるのは以下演算子だけ
- 加算(+)
- 減算(-)
- 乗算(*)
- 除算(/)
- 累乗(**)
- 余り(%)
- 他ビット演算子
また Math 関係に対して使うことも不可です。
それ以外は普通の整数型と変わらないですね。
BigIntによる余りの求め方コード例
ではBigIntの実用的な使い方について。
入試とかでよくある巨大数の余りを求める例です。
普通は合同式(mod)とか利用するみたいですが、それを BigInt を使ってひたすら力技で求めるコードを書いてみました。 BigInt の実用的な例として紹介します。
有名な例題を解いてみると以下の通り。
2の100乗を7で割った余りを求めるコード例
次コードで求めることが可能。
1 2 3 4 5 6 7 |
var x = 1n; var n = 100; for(var i = 0; i < n; i++){ x *= 2n; } console.log('answer : ', x % 7n); /// answer : 2 |
答えは 2
人間にはできない本当の力技です・・・(-_-)
ただし最後の 7 で割るとき、 x % 7 だとエラーが出ます。
必ず x % 7n のようにBigInt型で割ることに注意です。
3の100乗を19で割った余りを求めるコード例
次のコードで求めることが可能
1 2 3 4 5 6 7 |
var x = 1n; var n = 100; for(var i = 0; i < n; i++){ x *= 3n; } console.log('answer : ', x % 19n); /// answer : 16 |
答えは 16
7の100乗を5で割った余りを求めるコード例
次のコードで求めることが可能
1 2 3 4 5 6 7 |
var x = 1n; var n = 100; for(var i = 0; i < n; i++){ x *= 7n; } console.log('answer : ', x % 5n); /// answer : 1 |
答えは 1
4の200乗を9で割った余りを求めるコード例
次のコードで求めることが可能
1 2 3 4 5 6 7 |
var x = 1n; var n = 200; for(var i = 0; i < n; i++){ x *= 4n; } console.log('answer : ', x % 9n); /// answer : 7 |
答えは 7
5の50乗を13で割った余りを求めるコード例
これは次のコードで求めることが可能
1 2 3 4 5 6 7 |
var x = 1n; var n = 50; for(var i = 0; i < n; i++){ x *= 5n; } console.log('answer : ', x % 13n); /// answer : 12 |
答えは 12
aのn乗をbで割った余りを求める汎用的コード
この問題では、汎用的なコードを定義することも可能です。
たとえば次みたいに関数化してみました。
▼ このような関数を作成
1 2 3 4 5 6 7 |
function modOfBigInt(a, n, b){ var x = 1n; for(var i = 0; i < n; i++){ x *= a; } return x % b; } |
▼ 2の100乗を2016で割った余り
1 2 3 |
var answer = modOfBigInt(2n, 100n, 2016n); console.log('answer : ', answer); /// andwer : 1024 |
こうすれば「aのn乗をbで割った余りを求めたい!」という場面ですぐ求められて便利です。まあ日常生活の中ではないですが・・・
数学問題の答えがあってるか調べるには便利かも。
BigIntは整数限定だけど巨大数を扱うのに便利
ここでは数学的な問題を無理やり BigInt で解いてみました。
もちろん数学的な意義はないですし、合同式など規則性を使って求めるのがスマートなのは言うまでもありません。2の100乗を力技で計算できる人間はほぼいないので。
とはいえ整数の巨大数を扱うには便利かもしれません。
特にマンパワーで対応できない問題では BigInt が役立ちそうです。