我有一个长约10分钟或更长时间的循环,我想总是设置一个新的时间来避免它继续。但它不起作用。
function problem3(){
var img = document.getElementById('p_3');
img.style.display = img.style.display === 'block' ? 'none' : 'block';
var number=600851475143;
var t = new Date();
for(var i=3;i*i<=number;i+=2){
if(isPrime(i) && number%i==0){
var maxPrime = i;
}
setInterval(function(){time(t)},5000);
}
document.getElementById("p3").innerHTML = 'Il più grande divisiore primo di <span>'+number+"</span> è <span>" + maxPrime+"</span>";
}
function time(t){
return console.log(Date() - t);
}
如果我将console.log(Date() - t);
放在problem3()函数中它可以工作,但我不能每5秒执行一次Date() - t,类似于setInterval(Date()-t,5000)
答案 0 :(得分:2)
在这种情况下,您可以考虑使用workers API。不要冻结浏览器,而是让工作在后台完成,并在完成后回调主线程。
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
答案 1 :(得分:1)
JavaScript不是多线程的。因此,我们将setInterval()视为每n
ms运行一段代码(在您的示例中为5000)。但那不是真的。如果在间隔过去时脚本已经运行,那么最好的情况就是将一些代码添加到要执行的队列中 - 但是在已经运行的脚本完成之前,该队列中的任何内容都不会运行。
粗略地说,这就是为什么它不起作用,但该怎么办?好吧,如果你想在problem3()返回之前发生任何事情,那么problem3()必须以同步的方式实现它。
例如,您可以创建一个lastOutputTime
变量,将其初始化为当前时间,并在每次迭代时通过for循环将当前时间与存储值进行比较。如果已经过了5秒,则输出到控制台并更新lastOutputTime
。
答案 2 :(得分:1)
您的算法应该改进为:
function maxPrimeFactor(number) {
if (number == 0 || !Number.isInteger(number) ||
number > Number.MAX_SAFE_INTEGER) return NaN;
number = Math.abs(number);
while(number % 2 == 0) number /= 2;
for (var i = 3; i * i <= number; i += 2) {
while(number % i == 0) number /= i;
}
return number;
}
var number = 600851475143;
console.log('maxPrimeFactor(' + number + ') == ' + maxPrimeFactor(number));
&#13;
如果某些数字需要太多时间,那么将循环分解为更小的块并进行异步。但从不使用setInterval
来实现此,尤其是永远不会在长循环中使用setInterval
。 setInterval
计划某些任务运行每 n
毫秒,因此如果您在循环中使用它,则在i
次迭代后,任务将运行{{1}每i
毫秒!并且n
是如此有问题,因为如果任务花费的时间超过setInterval
毫秒,它就会冻结浏览器。您应该使用n
代替。
但是,在这种情况下,这将毫无用处。上面的算法几乎可以立即检测到setTimeout
(15位)是素数。鉴于最大安全整数为304250263527209
(16位),我认为您的任何数字都不会有问题。
如果你说算法需要这么长时间,可能是因为你正在尝试使用更大的数字。但要注意JS数字是64位浮点数,因此整数不能在9007199254740991
之上准确表示。无论如何你都会得到错误的结果,所以甚至不要尝试计算它。
对于Project Euler#551,蛮力方法将是
Number.MAX_SAFE_INTEGER
&#13;
当然,暴力不是解决问题的适当方法。