【问题标题】:JS function to detect primes not working correctly检测素数不能正常工作的 JS 函数
【发布时间】:2021-04-20 18:17:54
【问题描述】:

我正在尝试创建一个函数来确定一个数字在 JS 上是否为素数。我使用的方法是威尔逊定理,简而言之,如果(num - 1)! % num 等于num -1,那么num 是素数。为了实现这个函数,我制作了另一个函数来计算给定数字的阶乘。我还添加了一个条件运算符,如果给定的数字小于或等于 1,则返回 false,以满足素数的条件。

阶乘函数工作得很好(我检查了它的返回值),但由于某种原因,威尔逊定理函数存在问题。我处理了很多素数,并确定低于 23 的函数将起作用,而高于 29(23 之后的第一个素数)函数将不起作用(包括 29)。

现在,我知道有很多更简单的方法可以实现用于此目的的函数,但我想尝试使用威尔逊定理,但我真的不明白为什么这个函数不起作用。您可以在下面看到我的代码和我为该功能所做的测试。如果您发现我的代码可能存在的任何问题,或者如果您知道我可以改进我的功能以达到更高的优化或解决我的问题的任何方法,请发表评论。提前致谢。

// Factorial function
let factorial = function(num) {
  let outp = 1;
  for (let i = 1; i <= num; i++) {
      outp *= i;
  }
  return outp;
}

// Prime tester function
let isPrime = x => x <= 1 ? false : factorial(x-1) % x == x-1;

// Test function
console.log(isPrime(7));  // Should return: true, returns: true
console.log(isPrime(23));  // Should return: true, returns: true
console.log(isPrime(29));  // Should return: true, returns: false
console.log(isPrime(101));  // Should return: true, returns: false

如果相关,我使用的是 node.js,但我也在在线编译器上对其进行了测试,并没有发现任何差异。

【问题讨论】:

  • 主要问题是计算阶乘非常昂贵,并且由于数字表示的限制,您无法准确地计算超出相对较低的阈值。一个简单的经典“Seive”实现会更加更有效率。
  • @Pointy 我想这是有道理的。但是,它仍然困扰着我,该函数将通过返回 false 而不是 undefined 或引发内部错误而失败。无论如何感谢您的回答,我会确保检查该实现方法。
  • 一个 JavaScript 数字只保留大约 17 位小数 (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…) 但 29!大约 30 位数长。您在没有足够精确度的情况下要求平等......
  • @JayBuckman 是的,显然这正是问题所在。感谢您的回答和参考,我一定会检查的。

标签: javascript node.js function primes factorial


【解决方案1】:

现代版本的 Javascript 支持任意精度整数 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt),可用于精确计算大整数:

// Factorial function
let factorial = function (num) {
    let outp = 1n; // the `n` suffix indicates a `BigInt` constant
    for (let i = 1n; i <= num; i++) {
        outp *= i;
    }
    return outp;
}

// Prime tester function
let isPrime = x => x <= 1n ? false : factorial(x - 1n) % x == x - 1n;

// Test function
console.log(isPrime(7n));  
console.log(isPrime(23n)); 
console.log(isPrime(29n)); 
console.log(isPrime(101n));

【讨论】:

  • 这真的很有帮助,感谢您的回答。它实际上修复了我的代码。显然,我可以使用该数据类型计算更大的素数,但我意识到这种方法并不是那么有效。
【解决方案2】:

它不适用于 29 和更大的数字的原因是 JavaScript 精度限制。 29!数字太大而无法存储,所以它有点四舍五入。 (对于更大的数字,它甚至可以是无穷大)。您可以将号码存储为字符串或数组。但是你必须自己实现乘法。

【讨论】:

  • 非常感谢!我不知道,但这很有意义。如果我将它存储在一个字符串中,也许它会起作用,我会尝试的。
猜你喜欢
  • 1970-01-01
  • 2013-03-06
  • 2014-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-17
  • 2013-04-09
相关资源
最近更新 更多