【发布时间】:2014-08-01 11:37:10
【问题描述】:
在玩 swift 教程时,我开始编写自定义 isPrime 方法来检查给定的 Int 是否为素数。
写完之后,我意识到它工作正常,但发现在一些相当大的数字上执行isPrime有点慢(仍然比Int.max低得多)。
所以我在 objc 中编写了相同的代码,并且代码执行得更快(66 倍)。
这里是快速代码:
class Swift {
class func isPrime(n:Int) -> Bool {
let sqr : Int = Int(sqrt(Double(n))) + 1
for i in 2...sqr {
if n % i == 0 {
return false
}
}
return true;
}
class func primesInRange(start:Int, end:Int) -> Int[] {
var primes:Int[] = Int[]()
for n in start...end {
if self.isPrime(n) {
primes.append(n)
}
}
return primes;
}
}
还有 objc 代码:
@implementation Utils
+ (BOOL)isPrime:(NSUInteger)n {
NSInteger sqr = (NSUInteger)(sqrt(n))+1;
for (NSUInteger i = 2; i < sqr; ++i) {
if (n % i == 0) {
return false;
}
}
return YES;
}
+ (NSArray*)primesInRange:(NSUInteger)start end:(NSUInteger)end {
NSMutableArray* primes = [NSMutableArray array];
for (NSUInteger i = start; i <= end; ++i) {
if ([self isPrime:i])
[primes addObject:@(i)];
}
return primes.copy;
}
@end
在main.swift:
let startDateSwift = NSDate.date()
let swiftPrimes = Swift.primesInRange(1_040_101_022_000, end: 1_040_101_022_200)
let elapsedSwift = NSDate.date().timeIntervalSinceDate(startDateSwift)*1000
let startDateObjc = NSDate.date()
let objcPrimes = Utils.primesInRange(1_040_101_022_000, end: 1_040_101_022_200)
let elapsedObjc = NSDate.date().timeIntervalSinceDate(startDateObjc)*1000
println("\(swiftPrimes) took: \(elapsedSwift)ms");
println("\(objcPrimes) took: \(elapsedObjc)ms");
这会产生:
[1040101022027, 1040101022039, 1040101022057, 1040101022099, 1040101022153] took: 3953.82004976273ms
[1040101022027, 1040101022039, 1040101022057, 1040101022099, 1040101022153] took: 66.4250254631042ms
我知道我可以在 Int 上使用 extension 来检查一个数字是否为素数,但我希望两个代码非常相似。
谁能告诉我为什么这个 swift 代码这么慢? 66 倍系数非常可怕,而且随着范围的增加只会变得更糟。
【问题讨论】:
-
你看过生成的汇编代码了吗?我认为,这会很有启发性。
-
首先,把测试的顺序颠倒一下,看看结果是否一样。我不明白为什么在这种情况下它很重要,但在其他情况下你肯定会得到缓存效果等。
-
@cmaster xcode 6 (6A215l) 似乎还不支持
Assembly View的 swif。 @“Tom Zych”是的,我也尝试过,但结果相同。 objc 以任何顺序快速运行。 -
未优化的 Swift 很慢。看这里:stackoverflow.com/questions/24101718/…
-
我认为
for i in 2...sqr应该是for i in 2..sqr。您在 Swift 中包含 i=sqr 而不是 Obj-C。 ... vs .. swift 中这样的错误。
标签: performance swift primes