免责声明:在SO上有类似的问题,然而 它们都不能解决算法的效率问题 用不同的语言写的。见this answer会谈 关于 python 的效率,看看它是否有助于你回答我的问题。
因此,我需要最有效的方法来查找任何给定数字的所有因素,这些因素可以使用非常大的数字快速运行。我已经有几个代码迭代工作,但需要很长时间才能处理超过6个字符的数字。
编辑:根据要求,这是我的一些非有效的方法(为清晰起见,遗漏了错误检查)
真的很乱:
@IBAction func findFactorsButton(_ sender: AnyObject) {
if let _ = textField.text, !textField.text!.isEmpty {
counter = 1
factors = []
repeat {
counter += 1
if Int(textField.text!)! % counter == 0 {
factors.append(String(counter))
} else {
continue
}
} while counter != Int(textField.text!)
factors.removeLast()
outputLabel.text = factors.joined(separator: ", ")
} else {
outputLabel.text = ""
}
}
不那么凌乱的解决方案(游乐场):
func calculateFactors(n: Int) -> String {
var result: String = ""
for i in 1...n {
guard n % i == 0 else {continue}
result += i == 1 ? "1" : ", \(i)"
}
print(result)
return result
}
答案 0 :(得分:5)
引用的Q& A What is the most efficient way of finding all the factors of a number in Python?中的大多数Python方法都使用了这样的事实
n
的因子成对出现:如果i
是一个因素,则n/i
是另一个因素
因子。因此,测试直至平方根的因子就足够了
给定数字。
以下是Swift中可能的实现:
func factors(of n: Int) -> [Int] {
precondition(n > 0, "n must be positive")
let sqrtn = Int(Double(n).squareRoot())
var factors: [Int] = []
factors.reserveCapacity(2 * sqrtn)
for i in 1...sqrtn {
if n % i == 0 {
factors.append(i)
}
}
var j = factors.count - 1
if factors[j] * factors[j] == n {
j -= 1
}
while j >= 0 {
factors.append(n / factors[j])
j -= 1
}
return factors
}
说明:
reserveCapacity
用于避免数组重新分配。1...sqrtn
范围内的所有因素,
然后相应的因子n/i
以相反的顺序附加,
所以所有因素都在增加。sqrt(n)
是
没有列出两次。对于最多8位小数的数字,最多9,999次试用 需要划分。例 (在发布模式下编译的1.2 GHz Intel Core m5 MacBook上):
let start = Date()
let f = factors(of: 99999999)
print("Time:", Date().timeIntervalSince(start) * 1000, "ms")
print("Factors:", f)
输出:
Time: 0.227034091949463 ms Factors: [1, 3, 9, 11, 33, 73, 99, 101, 137, 219, 303, 411, 657, 803, 909, 1111, 1233, 1507, 2409, 3333, 4521, 7227, 7373, 9999, 10001, 13563, 13837, 22119, 30003, 41511, 66357, 81103, 90009, 110011, 124533, 152207, 243309, 330033, 456621, 729927, 990099, 1010101, 1369863, 3030303, 9090909, 11111111, 33333333, 99999999]
答案 1 :(得分:2)
这一切都取决于你的数字。这是一个很棒的summary:
"你的数字有多大?"确定要使用的方法:
- 小于2 ^ 16左右:查找表。
- 小于2 ^ 70左右:
Sieve of Atkin。这是众所周知的Sieve of Eratosthenes的优化版本。修改: Richard Brent's modification 在这种情况下,Pollard's rho algorithm可能会更好。- 少于10 ^ 50:Lenstra elliptic curve factorization
- 少于10 ^ 100:Quadratic Sieve
- 超过10 ^ 100:General Number Field Sieve
所以这一切都变成了选择算法并在Swift中实现它们的问题。因为你说你需要带有#34; 6个字符的数字"这意味着它们大概在2 ^ 17左右。所以它在该列表中的选项2:Atkin的Sieve或Pollard的rho的修改。