在https://www.codewars.com上做js练习碰到这样一道题。
下面是原题的说明
Instructions
Is Prime
Define a function isPrime/is_prime() that takes one integer argument and returns true/True or false/False depending on if the integer is a prime.
Per Wikipedia, a prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.
Example
isPrime(5)
=> true
Assumptions
- You can assume you will be given an integer input.
- You can not assume that the integer will be only positive. You may be
given negative numbers as well (or 0).
Sample Tests:
Test.expect(isPrime(0) === false, '0 is not prime');
Test.expect(isPrime(1) === false, '1 is not prime');
Test.expect(isPrime(2) === true, '2 is prime');
Instructions中告诉我们通过isPrime或is_prime方法对给定的数值进行判断,如果是质数返回true,如果不是质数则返回fasle.
在Example和Sample Tests中提供了测试样例。
Assumptions中则说明了参数是整数,但没有指定正负值或者0.
质数只能被1和本身整除(1除外)
这一题,我考虑了一会想到了一个比较笨的办法。
function isPrime(num) {
if ( num <= 0 || num === 1 ) {
return false
}
let count = 0
for (let i = 1; i < num + 1; i++) {
if (num % i === 0) {
count ++
}
}
return count > 2 ? false : true
}
这测试通过了,但是这种方法如果不优化那我自己都不敢说这是解题答案了,尽管通过测试,但是比较繁琐和死板。
优化1
function isPrime(num) {
if ( num <= 0 || num === 1 ) {
return false
}
let count = 0
for (let i = 1; i < num + 1; i++) {
if (num % i === 0) {
count ++
}
if (count > 2) {
break
}
}
return count > 2 ? false : true
}
增加了判断
if (count > 2) {
break
}
这个当数值很大时,不会一直循环直到 i > num + 1
时才停止循环,
然而这个还是可以优化的
我们在通过修改判断条件是运算num % i === 0
相对于上面的代码少进行一次。
function isPrime(num) {
if ( num <= 0 || num === 1 ) {
return false
}
let count = 0
for (let i = 1; i < num + 1; i++) {
if (num % i === 0) {
count ++
}
if (count === 2 && i < num) { ///修改判断条件
return false
break
}
}
return count > 2 ? false : true
}
题外话:第一种方法不可取,因为没有对循环作一定的处理,当给定的数值特别大时占用特别大的内存,甚至死机。我们实际测试下。如果不对循环进行处理。
写一个函数计算上面的函数执行时间
function getDealTime() {
var start = new Date().getTime()
func()
var end = new Date().getTime()
return (end - start)+"ms"
}
原函数改写下
function isPrime() {
let num = 255555555555555555555555555555555555555555555555
if ( num <= 0 || num === 1 ) {
return false
}
let count = 0
for (let i = 1; i < num + 1; i++) {
if (num % i === 0) {
count ++
}
}
return count > 2 ? false : true
}
执行
getDealTime(isPrime)
不用我说结果,都可以知道没有对循环做处理的代码是多么危险了。所以在实际的项目中。也要谨慎适用循环,能不用循环就不用循环,或者根据场景减少循环的次数。