Если вы хотите быстро исправить, объявите C
и D
внутри функции calculate()
.
Вам не нужно находить все делители, чтобы проверить, является ли число простым или нет. Как только вы найдете a делитель, число не будет простым.
Вот более эффективный способ проверки, является ли текст в текстовом поле простым или нет:
@IBAction func calculate(_ sender: Any)
{
guard let number = Int(numberIN.text!) else
{
fatalError("Not a number")
}
let isPrime = checkIfPrime(number)
labelOUT.text = isPrime ? "prime" : "not prime"
}
Вызывает эту функцию, чтобы проверить, простое ли number
:
func checkIfPrime(_ n: Int) -> Bool
{
switch n
{
case ...1:
return false
case 2...3:
return true
default:
var isPrime = true
let maximumPossibleDivisor = Int(sqrt(Double(n)))
var divisor = 2
repeat
{
if (n % divisor == 0)
{
isPrime = false
break
}
divisor += 1
} while (divisor <= maximumPossibleDivisor)
return isPrime
}
}
Используется тот факт, , что у составного числа есть делитель между 2 и его корневым квадратом.
Более эффективная версия checkPrime()
использует тот факт, что простые числа, кроме 2
и 3
, можно записать как 6X - 1 или 6X + 1
func checkIfPrime(_ n: Int) -> Bool {
switch n {
case ...1:
return false
default:
if n % 2 == 0 || n % 3 == 0
{
return false
}
let maximumPossibleDivisor = Int(sqrt(Double(n)))
var divisor = 5
while (divisor <= maximumPossibleDivisor)
{
if n % divisor == 0 || n % (divisor + 2) == 0
{
return false
}
divisor += 6
}
return true
}
}
Вот симпатичный способ проверки простоты числа с помощью регулярного выражения:
extension Int {
func isPrime() -> Bool {
guard self >= 0 else { fatalError("Primality is only checked for positive numbers") }
let regex = try! NSRegularExpression(pattern: "^.?$|^(..+?)\\1+$")
let str = Array(repeating: "1", count: self).joined()
let range = NSMakeRange(0, self)
return regex.matches(in: str, range: range).count == 0
}
}
Принцип работы регулярного выражения подробно объясняется в здесь и там .
Подробнее о тестах на простоту смотрите здесь .