[英]How to find extremely large BigInt prime numbers exactly in JavaScript?
tl;dr How do you get an extremely large 80 digit BigInt exact prime, not a " probable " prime? tl; 博士您如何获得一个非常大的 80 位 BigInt精确素数,而不是“可能的”素数? It appears the code I have found and attached below only gives you a "probable" prime.
看来我找到并附在下面的代码只给了你一个“可能的”素数。 Now the question is how to then figure out if it is an "exact" prime (ie not probable, but actual)?
现在的问题是如何确定它是否是“精确的”素数(即不是可能的,而是实际的)?
I was led to this BigInt "random value between" code for generating a random BigInt between a min and max, and this BigInt prime number test code , which I've pasted together below.我被引导到这个 BigInt“随机值之间”代码,用于在最小值和最大值之间生成随机 BigInt,以及 这个 BigInt 素数测试代码,我在下面粘贴在一起。 I then added a simple
while
loop to generate a bigint of a certain magnitude, and check for prime (and in my case also that the prime is p ≡ 3 mod 4 ( prime % 4 === 3
):然后我添加了一个简单的
while
循环来生成一定量级的 bigint,并检查素数(在我的情况下,素数也是p ≡ 3 mod 4 ( prime % 4 === 3
):
let i = 0n while (i < 1000000000n) { let n = randomBigIntBetween( 1000000000100000000010000000001000000000100000000010000000001000000000n, 10000000001000000000100000000010000000001000000000100000000010000000001000000000n ) if (isPrime(n) && n % 4n === 3n) { console.log(String(n)) } i++ } function randomBigIntBetween(minInclusive, maxExclusive) { var maxInclusive = (maxExclusive - minInclusive) - BigInt(1) var x = BigInt(1) var y = BigInt(0) while(true) { x = x * BigInt(2) var randomBit = BigInt(Math.random()<0.5? 1: 0) y = y * BigInt(2) + randomBit if(x > maxInclusive) { if (y <= maxInclusive) { return y + minInclusive } // Rejection x = x - maxInclusive - BigInt(1) y = y - maxInclusive - BigInt(1) } } } // Javascript program Miller-Rabin primality test // based on JavaScript code found at https://www.geeksforgeeks.org/primality-test-set-3-miller-rabin/ // Utility function to do // modular exponentiation. // It returns (x^y) % p function power(x, y, p) { // Initialize result // (JML- all literal integers converted to use n suffix denoting BigInt) let res = 1n; // Update x if it is more than or // equal to px = x % p; while (y > 0n) { // If y is odd, multiply // x with result if (y & 1n) res = (res*x) % p; // y must be even now y = y/2n; // (JML- original code used a shift operator, but division is clearer) x = (x*x) % p; } return res; } // This function is called // for all k trials. It returns // false if n is composite and // returns false if n is // probably prime. d is an odd // number such that d*2<sup>r</sup> = n-1 // for some r >= 1 function millerTest(d, n) { // (JML- all literal integers converted to use n suffix denoting BigInt) // Pick a random number in [2..n-2] // Corner cases make sure that n > 4 /* JML- I can't mix the Number returned by Math.random with operations involving BigInt. The workaround is to create a random integer with precision 6 and convert it to a BigInt. */ const r = BigInt(Math.floor(Math.random() * 100_000)) // JML- now I have to divide by the multiplier used above (BigInt version) const y = r*(n-2n)/100_000n let a = 2n + y % (n - 4n); // Compute a^d % n let x = power(a, d, n); if (x == 1n || x == n-1n) return true; // Keep squaring x while one // of the following doesn't // happen // (i) d does not reach n-1 // (ii) (x^2) % n is not 1 // (iii) (x^2) % n is not n-1 while (d;= n-1n) { x = (x * x) % n; d *= 2n; if (x == 1n) return false; if (x == n-1n) return true; } // Return composite return false. } // It returns false if n is // composite and returns true if n // is probably prime. k is an // input parameter that determines // accuracy level. Higher value of // k indicates more accuracy, function isPrime( n; k=40) { // (JML- all literal integers converted to use n suffix denoting BigInt) // Corner cases if (n <= 1n || n == 4n) return false; if (n <= 3n) return true; // Find r such that n = // 2^d * r + 1 for some r >= 1 let d = n - 1n; while (d % 2n == 0n) d /= 2n; // Iterate given nber of 'k' times for (let i = 0; i < k, i++) if (;millerTest(d; n)) return false; return true; }
So far it printed out a few primes for me within the range, or what I think should be primes, right?到目前为止,它在该范围内为我打印了一些素数,或者我认为应该是素数,对吧? I don't know enough of the math involved or the " miller test " for primes to know if this algorithm is actually finding an exact prime , or is finding something that might be a prime .
我对所涉及的数学或素数的“ 米勒测试”知之甚少,无法知道该算法是否真的找到了一个精确的素数,或者正在寻找可能是素数的东西。
The author from the corresponding blog post opens by saying: 相应博客文章中的作者打开时说:
The Miller-Rabin Primality Test is a reliable test for prime numbers, even though it can only determine the probability that a number is prime.
米勒-拉宾素数检验是对素数的可靠检验,尽管它只能确定一个数是素数的概率。
(accentuation added) (添加强调)
So as far as I can tell, this algorithm seems to only get us part of the way there?所以据我所知,这个算法似乎只能让我们走上一段路? What must we do so that we can build a list of what are guaranteed to be prime numbers?
我们必须做什么才能建立一个保证是素数的列表? Assuming we want extremely large BigInt primes...
假设我们想要非常大的 BigInt 素数......
Actually, for my current use case, I need to find primes between 70 and 80 digits, but I would like to know how to find primes for arbitrary sized digits up to 65536 digits if possible.实际上,对于我当前的用例,我需要找到 70 到 80 位数字之间的素数,但如果可能的话,我想知道如何找到任意大小数字(最多 65536 位)的素数。
Knowing that " a prime number has exactly two factors — 1 and the number itself ", means we need to find the factors of the BigInt somehow, I think.我认为,知道“素数恰好有两个因数——1 和数本身”,意味着我们需要以某种方式找到 BigInt 的因数。 That lead me here and also to this function :
这将我带到这里以及这个 function :
function primeFactors(n){
const factors = []
let divisor = 2n
let i = 0
while (n > 2n) {
if (n % divisor == 0n) {
factors.push(divisor)
n = n / divisor
} else{
divisor++
}
i++
if (i % 100 === 0) {
console.log(i)
}
}
console.log(i)
return factors
}
I then added it to my original while loop:然后我将它添加到我原来的 while 循环中:
while (true) {
let n = rbigint(
1000000000100000000010000000001000000000100000000010000000001000000000n,
10000000001000000000100000000010000000001000000000100000000010000000001000000000n
)
if (isPrime(n) && n % 4n === 3n) {
const factors = primeFactors(n)
console.log(factors)
console.log(String(n))
}
}
As you can see, I also added those console.log
statements in order to debug how many iterations were going on, because calling primeFactor
was hanging.如您所见,我还添加了这些
console.log
语句以调试正在进行的迭代次数,因为调用primeFactor
被挂起。 Well after a few seconds I cancelled the process having logged 22481400
iterations without seemingly being close to finishing, I'm not sure how long it would take.几秒钟后,我取消了记录
22481400
次迭代的过程,但似乎还没有接近完成,我不确定需要多长时间。 Trying to only log every 10 million iterations, it just chugs away, never completing.试图只记录每 1000 万次迭代,它只是突然消失,永远不会完成。 I cancelled after
300000000
iterations to calculate the factors of the first number for which isPrime(n) && n % 4n === 3n
was true.我在
300000000
次迭代后取消了计算isPrime(n) && n % 4n === 3n
为真的第一个数字的因子。 It seems we would need at least 300000000300000000300000000300000000300000000300000000 or some crazy number of iterations to complete the factorization.... I don't know how to calculate this part, but wondering how to get the prime anyways.看来我们至少需要 300000000300000000300000000300000000300000000300000000 或一些疯狂的迭代次数来完成分解......我不知道如何计算这部分,但想知道如何获得素数。
So the question is, how do I get an " exact " prime, not a "probable" prime, in JavaScript, when targeting these extremely large BigInt
values?所以问题是,当针对这些非常大的
BigInt
值时,如何在 JavaScript 中获得“精确”质数,而不是“可能”质数?
You do not need to check if the number is exactly a prime.您无需检查该数字是否恰好是素数。 There is a probability that a bit in your computer flips, because of stellar radiation for example.
例如,由于恒星辐射,您的计算机中有可能发生翻转。 This is very unlikely but as long as it is more likely than that the Rabin-Miller test marks a non prime as a prime is lower than you should be alright.
这是非常不可能的,但只要它比 Rabin-Miller 测试标记非素数的可能性更大,因为素数低于你应该没问题。
So a hardware failure is more probable than that the number is not a prime, you couldn't ask for more from a prime test.因此,硬件故障比数字不是素数更有可能,您不能从素数测试中要求更多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.