【问题标题】:Javascript - Code for finding a list of prime numbers keeps freezingJavascript - 查找素数列表的代码一直冻结
【发布时间】:2016-04-22 12:33:00
【问题描述】:

在处理 Project Euler 的问题 3 时,我遇到了一个问题,我似乎无法解决 javascript 一直冻结的问题。这是我的代码:

var is_prime = function(n) {
  if (n === 1) {
    return true;
  }
  if (n === 2) {
    return true;
  }
  var list1 = []
  for (i = 2; i < n; i++) {
    list1.push(i);
  }
  for (i = 2; i < list1.length; i++) {
    if (n % i === 0) {
      return false;
    }
  }
  return true;
}

var list_of_primes = function(n) {
  var list1 = [];
  var list2 = [];
  for (i = 2; i < n; i++) {
    list1.push(i);
  }
  for (i = 2; i < list1.length; i++) {
    if (is_prime(i)) {
      list2.push(i);
    }
  }
  return list2;
}
confirm(list_of_primes(1000))

我知道我的算法不是最有效的,而且我只是在暴力破解问题,但我只是想知道我做错了什么。我很确定问题出在这段代码中的某个地方:

  for (i = 2; i < list1.length; i++) {
    if (is_prime(i)) {
    list2.push(i);
    }
  }

我认为一个潜在的问题是我的算法花费的时间太长,这就是导致 javascript 冻结的原因。有没有办法让我的问题运行足够长的时间来给我答案?

【问题讨论】:

  • “我知道我的算法不是最有效的......” 是不是你在暴力破解时只是在最大化 CPU?尝试让它在一夜之间运行,看看是否有任何结果。或者在循环中包含一些 console.log() 命令以定期输出 i 的“当前”值?
  • 我不认为我可以最大化我的 CPU。我设法让它在 python 上工作,答案只花了大约 1 秒。但是,当我尝试将此代码转换为 javascript 并在 jsfiddle 或 node.js 上运行时,它们都会在一秒钟内崩溃。
  • @OscarYih 你试过像 15 这样的小值吗?它肯定会更快地工作。如果它有效,则意味着您需要改用有效的算法。如果遇到任何错误,请检查浏览器上的控制台。
  • Python 在这种算法上可能比 Javascript 更有效。我已经编写了 Javascript,它在看似微不足道的输入上消耗了相当多的 CPU。这可能只是达到语言可以做的极限的情况。尝试在运行时监控您的 CPU,如果某个核心达到 100%,那么您很可能正在碰壁。特别是如果您使用 node.js 得到相同的行为(否则我会责怪目标浏览器中语言的草率实现)。
  • 等一下:这可能是因为你的两个函数都使用相同的全局变量i 作为循环计数器?

标签: javascript


【解决方案1】:

iis_prime 函数中的全局变量,它会干扰list_of_primes 函数中使用的实例。通过像这样将i 声明为本地来修复...

var is_prime = function(n) {
  var i; // <~~ declare i as local variable here
  if (n === 1) {

【讨论】:

    【解决方案2】:

    素数(或素数)是大于 1 的自然数,除 1 和自身之外没有正除数。

    严格来说,1 不是质数,因此请务必在您的代码中更新它。

    不太确定您的代码为什么会超时,它只是有点冗长并且有一个不必要的数组 (list1)。无论如何,这里有一个相当简短的代码版本,它提供了一个从 2 到 n 的素数列表。 这对于大数字集来说效率不高,因为它单独检查每个数字。

    var list_of_primes = function(n) {
      var list = [];
      for (i = 2; i < n; i++) {
        if (is_prime(i)) {
          list.push(i);
        }
      }
      return list;
    }
    function is_prime(i) {
      for (var c = 2; c <= Math.sqrt(i); ++c)
        if (i % c === 0)
          return false;
      return true;
    }
    

    如果您想要更高的效率,请查看Sieve of Eratosthenes,它可以处理更大的集合:

    // Credit: http://stackoverflow.com/a/15471749/1265817
    var eratosthenes = function(n) {
      // Eratosthenes algorithm to find all primes under n
      var array = [], upperLimit = Math.sqrt(n), output = [];
    
      // Make an array from 2 to (n - 1)
      for (var i = 0; i < n; i++) {
        array.push(true);
      }
      // Remove multiples of primes starting from 2, 3, 5,...
      for (var i = 2; i <= upperLimit; i++) {
        if (array[i]) {
          for (var j = i * i; j < n; j += i) {
            array[j] = false;
          }
        }
      }
      // All array[i] set to true are primes
      for (var i = 2; i < n; i++) {
        if(array[i]) {
          output.push(i);
        }
      }
      return output;
    };
    

    工作示例:https://jsfiddle.net/daCrosby/wfgq28no/

    【讨论】:

      【解决方案3】:

      你可以试试这个。

      var is_prime = function(n) {
       if (n == 1) {
         return true;
        }
       if (n == 2) {
         return true;
        }
      
        for (var i = 2; i < n; i++) {
          if (n % i == 0) {
            return false;
           }
           }
        return true;
        }
      
        var list_of_primes = function(n) {
        var list2 = [];
      
        for (var i = 2; i < n; i++) {
          if (is_prime(i)) {
               list2.push(i);
        }
        }
        return list2;
      }
      confirm(list_of_primes(1000))
      

      不到几秒钟就可以正常工作。 https://jsfiddle.net/LL85rxv5/

      【讨论】:

      • 感谢您的解决方案,我一定会将您的代码与我的代码进行比较,看看我做错了什么。
      猜你喜欢
      • 1970-01-01
      • 2017-05-23
      • 1970-01-01
      • 2020-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-26
      • 2014-05-01
      相关资源
      最近更新 更多