简体   繁体   English

如何在 JavaScript 中准确找到极大的 BigInt 素数?

[英]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 4prime % 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM