【问题标题】:Why does this for loop take so long?为什么这个for循环需要这么长时间?
【发布时间】:2016-02-19 00:33:30
【问题描述】:

我一直在处理 Project Euler 问题,在解决问题 3 时,我遇到了一些奇怪的事情。

问题 3 要求你“找出数字 600851475143 的最大质因数”

我是这样解决的:

var search = 600851475143;
var highest = 0;
var primes = [2,3,5,7,11];

function isPrime(num) {
    for (var i = 0; i < primes.length; i++) {
        if (num === primes[i]) {
            return true;
        }
        else if (num % primes[i] === 0) {
            return false;
        }
    }
    primes.push(num);
    return true;
}


for (var n = 2; n <= Math.floor(Math.sqrt(search)); n++) {
    if (isPrime(n) && search % n === 0) {
        highest = n;
    }
}

console.log(highest);

这花了 7534.188ms 这实际上是我的第二个版本的程序。

在第一个版本中,唯一的区别是在 isPrime 函数中声明的 for 循环中

i <= primes.length

当此更改到位时,程序花费了 72084.540 毫秒

从大约 8 秒增加到大约 72 秒,慢了 9 倍。

我不认为额外的迭代会导致时间增加。我最初的想法是,因为它正在寻找一个不存在的索引,但这肯定会使程序崩溃,而不仅仅是让它运行得更慢。

有人对此有任何见解吗?

【问题讨论】:

  • 因为search的值很大。您的循环使用 search 的值作为延续。你认为你在 n 等于搜索的 sqrt 之前增加了多少次?
  • “问题 3 要求您“找出数字 600851475143 的最大素因数””您是否尝试过从数字本身开始迭代?
  • 我无法找到从数字本身迭代的方法,因为 isPrime 函数需要所有先前的素数才能找到下一个。它是埃拉托色尼筛法的一种应用。

标签: javascript arrays for-loop


【解决方案1】:

您的外部循环迭代 775146 次。那是 600851475143 的 sqrt。您的内部循环至少迭代 5 次并增加。所以总的迭代次数至少是 3875730。这需要一段时间。

尝试插入对进入内循环的次数的计数。该计数将与代码的运行时间成正比。

【讨论】:

  • 每次找到素数时,内部循环的迭代次数都会增加。所以它不仅仅是 5,它只是从 5 开始。
  • 两个版本进入内循环 775145 次。我相信 Erik 的回答最有可能在这里。
【解决方案2】:

您的问题可能是由于在 Javascript 中,这段代码:

var primes = [2,3,5,7,11];
console.log(primes[12]);

产生输出undefined,即使primes[12] 超出了数组的范围。

在这方面,Javascript 与其他语言不同 - 超出数组范围不会导致崩溃,而是返回一个未定义的值并允许程序愉快地继续运行。 undefined 是一个可以存储在变量中的实际值,因此它将继续评估 if 语句并在最后一次迭代后退出循环。

undefined 的比较速度很慢,至少在 Chrome 中是这样。 See this Stackoverflow question for some performance information.

【讨论】:

  • 这不仅会导致程序崩溃,还会导致其运行缓慢吗?
  • 不,Javascript 在这方面不像其他语言 - 超出数组范围不会导致崩溃,而是返回 undefined 值并允许程序愉快地继续运行。 undefined 是一个可以存储在变量中的实际值,所以它会继续计算 if 语句并在最后一次迭代后退出循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-27
  • 2011-12-07
  • 2012-08-09
  • 2021-07-26
相关资源
最近更新 更多