我想要一个名为findFirst的函数,它接受参数n和q,并返回除以n大于或等于q的最小素数。所以首先我写了一个函数,可以说一个数字是否为素数。
var isPrime = function(n){
if(n === 1){
return false;
}
else if (n === 2 || n === 3){
return true;
}
else {
for(i=2; i < n; i++){
if(i * i >= n){
for(j=2; j<=i; j++){
if(n % j === 0){
return false;
}
}
return true;
}
}
}
};
可能有其他方法可以提高效率,但我很确定这个功能不是问题。
所以使用这个函数我第一次尝试编写findFirst:
var findFirst = function(n,q){
var p = q;
while(n % p !== 0 || isPrime(p) === false){
p++;
}
return p;
};
此功能有效,但是大数字会崩溃,例如它在输入时崩溃(6310545154,3)。顺便说一句6310545154的主要功率分解是2 * 3155272577
所以我写了另一个函数,首先列出数字的素因子:
var getFactors = function(n){
var factors = [];
var k = n;
var p = 2;
while(isPrime(k) === false && k !== 1){
while(k % p !== 0 || isPrime(p) === false){
p = p+1;
}
while(k % p === 0){
k = k/p;
}
factors.push(p);
}
if(isPrime(k) === true){
factors.push(k);
return factors;
}
if(k === 1){
return factors;
}
};
现在我对findFirst的第二次尝试是:
var findFirst = function(n,q){
var array = getFactors(n);
var p = 0;
for(i = 0; i < array.length; i++){
if(array[i] >= q && p === 0){
p = array[i];
}
}
return p;
};
这个很棒。它不会在上面那么大的数字上崩溃并立即计算结果。谁能明白为什么会这样呢?看起来我原始尝试中的'while'循环与getFactors函数中的'while'循环非常相似。而第二次尝试看起来要复杂得多。
答案 0 :(得分:3)
第二个程序返回非常快,因为你的数字只有一个大的素因子;一旦发现(全部)小的素数因子,它就会迅速退出循环。第一个程序在发现它是一个因素之前必须从3到3155272577一直计数。在2147483647之后,它必须从整数运算切换到浮点运算,这使得它更慢。
请注意
var isPrime = function(n) {
...
};
是一种创建函数的不寻常方式;通常你会写
function isPrime(n) {
...
}
答案 1 :(得分:0)
你在代码中有很多错误 - 例如,这种方式i
是全局变量
for(i=2; i < n; i++){
你想做的是
for(var i=2; i < n; i++){
之后
factors[i] = k;
未定义i
等等。
通过jslint或jshint运行代码,使其首先完全正确。
答案 2 :(得分:0)
您可以使用正则表达式快速检查素数。
function isPrimeNumber(n) {
return !/^1?$|^(11+?)\1+$/.test((new Array(++n)).join('1'));
}
详细了解this post。
编辑:虽然可能不适合大数字。更像是一个快速的解决方案。
答案 3 :(得分:0)
这并没有直接解决这个问题,但我认为重要的是要强调无响应的标签与崩溃不同。无响应只是意味着网页一直在执行JavaScript很久。
请记住,浏览器无法确定脚本是否会在不运行脚本的情况下完成 - 这称为暂停问题,,对于图灵完整的编程语言,它无法解决。浏览器杀死脚本的提议基于猜测,无论相关脚本是什么,都是如此。
答案 4 :(得分:0)
第二次尝试永远不会执行p = p+1;
,实际上只会在while
部分执行整个getFactors
2次:
while(k % p !== 0 || isPrime(p) === false){
p = p+1;
}
不同于第一次尝试必须测试来自&#39; 3&#39;的每个p
的数量。在第一次尝试中3155272577
的素数和因子为n
:
while(n % p !== 0 || isPrime(p) === false){
p++;
}
<强>为什么吗
第二次尝试以var p = 2;
和var k = n;
开头,这意味着(k % p === 0)
和isPrime(p)
都是true
(当n=6310545154
时)
while(isPrime(k) === false && k !== 1){
while(k % p !== 0 || isPrime(p) === false){
p = p+1; /* this is never executed for findFirst(6310545154, 3) */
}
while(k % p === 0){
k = k/p;
}
...
然后k = k/p;
立即将k
缩减为3155272577
,从而终止外部while(isPrime(k) === false ...
要在第二次尝试中观察相同的异常时间行为,请使用:
var factors = [2];
和var p = 3;
。