素数检查器 returns 每次都得到相同的结果

Prime number checker returns the same result each time

我是一名初级程序员,正在学习 Swift 并制作了一个基本的素数检查器。无论如何它只会给出一个结果,而不是根据数字是否为素数而改变。任何帮助将不胜感激。

@IBAction func primeCheck(sender: AnyObject) {

var numberInt  = number.text.toInt()
var isPrime = true

    if number != nil {        
        if numberInt == 1 {      
            isPrime = false
        }

        if numberInt != 1 {         
            for var i = 2; i < numberInt; i++ {        
                if numberInt! % i == 0 {
                    isPrime = false
                } else {
                    isPrime = true
                }
            }
        }

    }

    if isPrime == true {
        result.text = "\(numberInt!) is a prime number!"
    } else {
        result.text = "\(numberInt!) is not a prime number!"
    }

}

嗯,我不知道 swift,但也许这会破坏您的代码:

if numberInt! <<

要执行更快的算法,您只需搜索从 2 到 sqrt(numberInt) 的除数。 (定理)

当你发现这个数字可以被另一个数字整除后,你必须跳出循环。同样对于质数检查,您只需要检查除数直到数字的平方根。

您还可以使用可选绑定来提取 numberInt 并检查是否为 nil。这就是 swift 方式。

@IBAction func primeCheck(sender: AnyObject) {

    var isPrime = true
    if let numberInt  = number.text.toInt() {

        if numberInt == 1 {
            isPrime = false /
        }
        else // Add else because you dont have to execute code below if number is 1
        {
            if numberInt != 1 {
                for var i = 2; i * i <= numberInt; i++ { // Only check till squareroot
                    if numberInt % i == 0 {
                        isPrime = false
                        break // Break out of loop if number is divisible.

                    } // Don't need else condition because isPrime is initialised as true.
                }
            }
        }

       if isPrime {
          result.text = "\(numberInt) is a prime number!"
       } else {
          result.text = "\(numberInt) is not a prime number!"
       }
    }

}

平方根检查的原因:Why do we check up to the square root of a prime number to determine if it is prime?

您可以通过将质数检查重构为一个单独的函数来进一步优化代码。

func isPrime(number:Int) -> Bool
{
    if number == 1 {
        return false
    }
    else
    {
        if number != 1 {
            for var i = 2; i * i <= numberInt; i++ {
                if numberInt % i == 0 {
                    return false
                }
            }
        }
    }
    return true
}

@IBAction func primeCheck(sender: AnyObject) {

    if let numberInt  = number.text.toInt() {

        if isPrime(numberInt) {
            result.text = "\(numberInt) is a prime number!"
        } else {
            result.text = "\(numberInt) is not a prime number!"
        }
    }

}

您的逻辑错误出现在这部分:

if numberInt! % i == 0 {
    isPrime = false
} else {
    isPrime = true
}

在你的函数的顶部,你将 isPrime 初始化为真,所以在你的循环中你只需要寻找证明数字是 而不是 的情况主要。您永远不需要再次设置 isPrime = true,所以只需删除 else 条件:

if numberInt! % i == 0 {
    isPrime = false
}

你这里其实有两个功能。一个检查数字是否为质数,另一个显示结果。将它们分开会使一切更容易管理。

// function to check primality and return a bool
// note that this can only accept a non optional Int so there is
// no need to check whether it is valid etc...
func checkNumberIsPrime(number: Int) -> Bool {
    // get rid of trivial examples to improve the speed later
    if number == 2 || number == 3 {
        return true
    }

    if number <= 1 || number%2 == 0 {
        return false
    }

    // square root and round up to the nearest int
    let squareRoot: Int = Int(ceil(sqrtf(Float(number))))

    // no need to check anything above sqrt of number
    // any factor above the square root will have a cofactor
    // below the square root.
    // don't need to check even numbers because we already checked for 2
    // half the numbers checked = twice as fast :-D
    for i in stride(from: 3, to: squareRoot, by: 2) {
        if number % i == 0 {
            return false
        }
    }

    return true
}

// function on the button. Run the check and display results.
@IBAction func primeCheck(sender: AnyObject) {
    let numberInt? = numberTextField.text.toInt() // don't call a text field "number", it's just confusing.

    if let actualNumber = numberInt {
        if checkNumberIsPrime(actualNumber) {
            resultLabel.text = "\(actualNumber) is a prime number!" // don't call a label "result" call it "resultLabel". Don't confuse things.
        } else {
            resultLabel.text = "\(actualNumber) is not a prime number!"
        }
    } else {
        resultLabel.text = "'\(numberTextField.text)' is not a number!"
    }
}

它使阅读和维护变得更加容易。

我有另一种可能的解决方案。起初我除以二,因为它不可能是质数。然后你循环直到数字是质数或数字除以二小于除数。

@IBAction func primeCheck(sender: AnyObject) {

    var numberInt  = number.text.toInt()
    var isPrime = true
    var divider = 3

    if number < 2 || (number != 2 && number % 2 == 0) {
        isPrime = false
    }

    // you only have to check to half of the number
    while(isPrime == true && divider < number / 2){
        isPrime = number % divider != 0
        divider += 2
    }

    if isPrime == true {
        result.text = "\(numberInt!) is a prime number!"
    } else {
        result.text = "\(numberInt!) is not a prime number!"
    }
}