我正在编写代码以查找给定数字以下所有素数的总和(在这种情况下,我希望找到2000000)
我的代码可以很好地运行20000以下的数字,但是当我加0时,它不会。
我试图在codeandbox上运行它,它会告诉我某处可能存在无限循环。
const isPrime = number => {
let k=0
for (let i=2; i < number; i++) {
if (number % i === 0) {
k++
}
}
if (k === 0) {
return true
} else {
return false
}
}
const sumOfPrimes = limit => {
let primeSum = 0
for (let i=1; i <= limit; i++) {
if (isPrime(i)) {
primeSum += i
}
} console.log(primeSum);
}
sumOfPrimes(2000000);
答案 0 :(得分:2)
如果必须处理多达2,000,000的数字,那么这不是解决问题的正确方法。有许多用于确定数字是否为质数的算法,并且在算法的复杂性与大数的效率之间需要权衡。为了知道哪种算法适合您的用例,我们需要知道您的用例是什么。 (听起来您正在尝试解决课程或代码挑战中的给定问题。)
但是即使使用了所使用的算法,也有一些简单的方法可以加快它的速度。一方面,在isPrime
的循环中,当number % i === 0
时,您应该return false
而不是增加变量并稍后对其进行检查。这种变化本身应该可以极大地加快程序运行速度,因为大多数数字的除数很小,因此大多数数字只会在该循环中运行几次。
另一种简便的加速方法是限制循环播放的数字。您正在遍历从2到n的所有数字。但是要检查数字是否为质数,只需要按质数检查其可除性。如果您的目标是计算第一个但很多质数的总和,那么这很容易:建立一个质数列表,根据列表中已有的数字检查每个新候选数。我强烈怀疑这种方法是否足够快地满足您的需求。
答案 1 :(得分:1)
更有效的方法是使用Eratosthenes筛子。通常,这将返回一个达到给定限制的素数列表,但是使用reduce
进行少量修改后,您可以使其返回总和:
function sumOfPrimes(n) {
const nums = Array(n).fill(true);
nums[0] = nums[1] = false;
const sq = Math.sqrt(n);
for (let i = 2; i <= sq; i++) {
if (nums[i]) {
for (let j = i * i; j < n; j += i) nums[j] = false;
}
}
return nums.reduce((sum, a, i) => sum + (a && i), 0);
}
console.log(sumOfPrimes(10));
console.log(sumOfPrimes(2000000));
请注意,有一些方法可以获得更好的性能,例如segmented sieve of Eratosthenes。
答案 2 :(得分:0)
以为我会通过一个示例实现来备份https://twitter.com/KhaosT/status/1140814602017464320:
<TextView
android:id="@+id/txtLogo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/SSA0Logo"
android:textColor="@color/SSA0LogoText"
android:textSize="50sp"/>
const primes = [2, 3];
function isPrime (n) {
// eliminate base cases
if (n < 2) return false;
const sqrt = Math.sqrt(n);
let i;
// check if known primes are factors of n
for (i of primes) {
if (i > sqrt) break;
if (n % i === 0) return false;
}
// check if odd numbers between largest
// known prime and sqrt(n) are factors of n
for (i += 2; i <= sqrt; i += 2) {
if (n % i === 0) return false;
}
// prevents duplicate primes from being added
if (primes[primes.length - 1] < n) {
primes.push(n);
}
return true;
}
function sumOfPrimes (limit) {
let primeSum = 0;
for (let i = 1; i <= limit; i++) {
if (isPrime(i)) primeSum += i;
}
return primeSum;
}
console.log(sumOfPrimes(10));
console.log(sumOfPrimes(2000000));
是专门为增加输入isPrime()
而被调用而设计的。如果在较小的素数n
之前之前检查了较大的素数n
,则条件
n
将无法将较小的质数添加到已知质数列表中,但是由于这种用法不会发生这种情况,因此就足够了。