実現したいこと
JavaScriptで巨大な数(メルセンヌ数)が素数であるか判定したいです。
巨大な数とは、具体的には 2^100000000 (10進法表記で約3000万桁) 程度です。
前提
JavaScript V8 11.1.24.7
JavaScript
1let prime, n; 2for (n = 100000000n; ; n++) { 3 4 // 一度目のループ 5 // 2^n - 1 を計算する 6 if (!prime) prime = (2n ** n) - 1n; 7 // 2回目以降のループ 8 // 2^n - 1 を計算するとリソースを食うので、 9 // 一つ前の計算で求めた結果に1を足して2を掛けて1を引く 10 else prime = (prime + 1n) * 2n - 1n; 11 12 // 素数判定 13 if (IsPrime(n, prime)) 14 console.log("2^" + primejs.n + "-1 は素数です。"); 15}
JavaScript
1function IsPrime(n, num) { 2 // 高速化のため、素数番目以外のメルセンヌ数は除外 3 // 省略 4 5 // リュカ–レーマーのテスト 6 let s = 4n, M = (1n << num) - 1n; 7 for (let n = 2; n < num; n++) 8 s = (s ** 2n - 2n) % M; 9 10 if (s != 0n) return false; 11 12 // 素数の場合の処理 13 return true; 14} 15
発生している問題・エラーメッセージ
Uncaught RangeError: Maximum BigInt size exceeded 発生場所: `let s = 4n, M = (1n << num) - 1n;`
試したこと
リュカ–レーマーのテストを用いずに、単純に2からsqrt(num)までmodを行うと数がオーバーしません。
javascript
1function sqrt(value) { 2 let sqrt = value / 3n; 3 if (value <= 0n) return 0n; 4 for (let i = 0; i < 6; i++) 5 sqrt = (sqrt + value / sqrt) / 2n; 6 return sqrt; 7} 8function IsPrime(n, num) { 9 // 3以上かつ数字の平方根より小さい数で割り切れないか試す。numRoot mod n === 0 の時点で終了 10 // BigIntは小数点以下を扱わないため、Math.ceilは不要 11 let numRoot = sqrt(num); 12 for (let i = BigInt(3); i < numRoot; i++) 13 if (num % i === 0n) return false; 14 15 return true; 16}
しかし、それでは最大でsqrt(num)-2回のループ処理が必要となってしまうため、どうしてもリュカ–レーマーのテストをオーバーフローさせずに実行したいです。
そこで、BigIntの上限より大きな数を扱う方法若しくは巨大な数を登場させずに素数判定ができるアルゴリズムがあれば教えて頂きたいです。
宜しくお願いします。
回答1件
あなたの回答
tips
プレビュー