【问题标题】:How to find extremely large BigInt prime numbers exactly in JavaScript?如何在 JavaScript 中准确地找到极大的 BigInt 素数?
【发布时间】:2022-01-12 14:31:06
【问题描述】:

tl;dr你如何得到一个非常大的 80 位 BigInt 精确素数,而不是“可能”素数?看来我找到并附在下面的代码只会给你一个“可能的”质数。现在的问题是如何确定它是否是“精确”素数(即不是可能的,而是实际的)?


我被引导到this BigInt "random value between" code 用于生成介于最小值和最大值之间的随机 BigInt,以及 this BigInt prime number test code,我已将其粘贴在下面。然后我添加了一个简单的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 p
    x = 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;
}

到目前为止,它为我打印了该范围内的几个素数,或者我认为应该是素数,对吗?我对所涉及的数学或素数的“miller test”知之甚少,无法知道该算法是否真的找到了一个精确的素数,或者正在找到可能的东西是素数

corresponding blog post 的作者开口说:

米勒-拉宾素数检验是对素数的可靠检验,尽管它只能确定一个数为素数的概率。

(加了重音)

据我所知,这个算法似乎只能让我们走上一段路?我们必须做什么才能建立一个保证是素数的列表?假设我们想要非常大的 BigInt 素数......

实际上,对于我当前的用例,我需要找到 70 到 80 位之间的素数,但我想知道如何找到任意大小数字的素数,如果可能的话,最多 65536 位。

知道“素数正好有两个因数——1 和数本身”,我认为,意味着我们需要以某种方式找到 BigInt 的因数。这导致我herethis 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) &amp;&amp; n % 4n === 3n 为真的第一个数字的因子。看来我们至少需要 300000000300000000300000000300000000300000000300000000 或一些疯狂的迭代次数才能完成分解......我不知道如何计算这部分,但想知道如何得到素数。

所以问题是,在 JavaScript 中,当定位这些极大的 BigInt 值时,如何获得“精确”质数,而不是“可能”质数?

【问题讨论】:

  • 这似乎不是编码问题。这似乎是一道数学题,或许应该在math.stackexchange.com 提问?
  • 这绝对是一个编码问题,我真的想在这一秒写下这段代码。
  • 我在您的帖子中数了 6 个问号。您提出的问题是:您如何获得一个非常大的 80 位 BigInt 精确素数,而不是“可能的”素数?那么如何确定它是否是“确切的”素数(即不是可能的,而是实际的)? ...应该是素数,对吧?我对所涉及的数学知识了解得不够多…………这个算法似乎只能让我们部分到达那里?我们必须做什么才能建立一个保证是素数的列表?我如何获得“准确”的质数,而不是“可能的”质数...? 没有一个是关于代码的。每一个都与算法的数学有关。
  • 我所知道的最快的方法是产生保证素数的波克林顿定理的变体。实际上,用单个 MR 测试剔除非素数然后使用 ECPP 来证明结果的素数可能更快,但是 ECPP 是很多棘手的代码。即便如此,正如@MrSmith42 所说,计算机本身还不够可靠,无法让您 100% 确定结果是素数。
  • 感谢您的问题,我想为您提供所需的帮助,但我认为您的问题分为两部分。 1) 设计一种算法,该算法将计算“精确”素数(大约 80 到 65536 位数字),使用的计算量足够少,可以在人的一生中计算出来。 (math.stackexchange) 和 2) 在 JavaScript (stackoverflow) 中编码该算法。看起来你的问题仍然是#1。如何执行循环的 10^53 次迭代不是 JavaScript 问题——以现代计算机的速度执行是不可行的。你仍然需要一个有效的算法。

标签: javascript algorithm primes bigint


【解决方案1】:

您不需要检查数字是否正好是质数。例如,由于恒星辐射,您的计算机中有可能发生翻转。这是非常不可能的,但只要它比 Rabin-Miller 测试标记非素数的可能性更大,因为素数低于你应该没问题。

因此,硬件故障比数字不是质数更有可能,您不能从质数测试中要求更多。

【讨论】:

  • 它必须是一个素数,我正在尝试将它插入this equation,这是一个需要 a p ≡ 3 mod 4 prime 的 PRNG 函数。我想要一个这个 PRNG 可以用来生成最大 256 位的伪随机整数。
  • @Lance:你错过了他的观点。你不能保证它是素数,即使你使用一种可以保证产生素数的算法。
  • 我不明白,算法保证产生素数,但你不能保证它是素数? math people 说找到最多 100 位的素数是“容易”和“常规”的,但今天不可能超过 1000 位。那是我的问题,找到 100 位素数的算法是什么,而不是可能的?
  • @Lance,我认为他们的意思是算法可以保证产生素数,但硬件不能保证。这就是他们使用“可能”一词的原因。
  • @Lance:哪些“数学家”说“今天不可能超过 1000 位”? ECPP(一种不期望数字具有特殊形式的算法)证明的最大数的当前记录是 40000 位。例如,请参阅primes.utm.edu/top20/page.php?id=27
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-09-29
  • 2018-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-21
  • 1970-01-01
相关资源
最近更新 更多