簡體   English   中英

如何在 JavaScript 中准確找到極大的 BigInt 素數?

[英]How to find extremely large BigInt prime numbers exactly in JavaScript?

tl; 博士您如何獲得一個非常大的 80 位 BigInt精確素數,而不是“可能的”素數? 看來我找到並附在下面的代碼只給了你一個“可能的”素數。 現在的問題是如何確定它是否是“精確的”素數(即不是可能的,而是實際的)?


我被引導到這個 BigInt“隨機值之間”代碼,用於在最小值和最大值之間生成隨機 BigInt,以及 這個 BigInt 素數測試代碼,我在下面粘貼在一起。 然后我添加了一個簡單的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; }

到目前為止,它在該范圍內為我打印了一些素數,或者我認為應該是素數,對吧? 我對所涉及的數學或素數的“ 米勒測試”知之甚少,無法知道該算法是否真的找到了一個精確的素數,或者正在尋找可能是素數的東西。

相應博客文章中的作者打開時說:

米勒-拉賓素數檢驗是對素數的可靠檢驗,盡管它只能確定一個數是素數的概率。

(添加強調)

所以據我所知,這個算法似乎只能讓我們走上一段路? 我們必須做什么才能建立一個保證是素數的列表? 假設我們想要非常大的 BigInt 素數......

實際上,對於我當前的用例,我需要找到 70 到 80 位數字之間的素數,但如果可能的話,我想知道如何找到任意大小數字(最多 65536 位)的素數。

我認為,知道“素數恰好有兩個因數——1 和數本身”,意味着我們需要以某種方式找到 BigInt 的因數。 這將我帶到這里以及這個 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
}

然后我將它添加到我原來的 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))
  }
}

如您所見,我還添加了這些console.log語句以調試正在進行的迭代次數,因為調用primeFactor被掛起。 幾秒鍾后,我取消了記錄22481400次迭代的過程,但似乎還沒有接近完成,我不確定需要多長時間。 試圖只記錄每 1000 萬次迭代,它只是突然消失,永遠不會完成。 我在300000000次迭代后取消了計算isPrime(n) && n % 4n === 3n為真的第一個數字的因子。 看來我們至少需要 300000000300000000300000000300000000300000000300000000 或一些瘋狂的迭代次數來完成分解......我不知道如何計算這部分,但想知道如何獲得素數。

所以問題是,當針對這些非常大的BigInt值時,如何在 JavaScript 中獲得“精確”質數,而不是“可能”質數?

您無需檢查該數字是否恰好是素數。 例如,由於恆星輻射,您的計算機中有可能發生翻轉。 這是非常不可能的,但只要它比 Rabin-Miller 測試標記非素數的可能性更大,因為素數低於你應該沒問題。

因此,硬件故障比數字不是素數更有可能,您不能從素數測試中要求更多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM