Swift 处理数字真的很慢吗? [英] Is Swift really slow at dealing with numbers?

查看:70
本文介绍了Swift 处理数字真的很慢吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我在玩 swift 教程时,我开始编写一个自定义的 isPrime 方法来检查给定的 Int 是否是素数.

As I was playing around with a swift tutorial, I started to write a custom isPrime method to check if a given Int is prime or not.

写完之后我意识到它工作正常,但发现在一些相当的大数字上执行isPrime有点慢(仍然比Int.最大值).

After writing it I realized it was working properly but found it a bit slow to perform isPrime on some quite large numbers (still much lower then Int.max).

所以我在 objc 中编写了相同的代码,并且代码执行得更快(66 倍).

So I wrote the same piece of code in objc and the code was executed much faster (a factor of 66x).

这是快速代码:

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 来检查一个数字是否是素数,但我希望两个代码非常相似.

I know that I could have used an extension on Int here to check if a number is prime, but I wanted both code to be very similar.

谁能告诉我为什么这个 swift 代码这么慢?66 倍系数非常可怕,而且随着范围的增加只会变得更糟.

Can anyone tell me why this swift code is so much slower? The 66x factor is pretty scary and only gets worse as I increment the range.

推荐答案

以下是 Swift 编译器代码生成的优化级别(您可以在构建设置中找到它们):

Here are optimization levels for the Swift compiler's code generation (you can find them in Build Settings):

[-Onone] no optimizations, the default for debug.
[-O]     perform optimizations, the default for release.
[-Ofast] perform optimizations and disable runtime overflow checks and runtime type checks.

使用您的代码,我在不同的优化级别获得了这些时间:

Using your code I got these times at different levels of optimization:

[-Onone]

Swift: 6110.98903417587ms
Objc:  134.006023406982ms

[-O]

Swift: 89.8249745368958ms
Objc:  85.5680108070374ms

[-Ofast]

Swift: 77.1470069885254ms
Objc:  76.3399600982666ms

请记住,-Ofast 是有风险的.例如它会默默地忽略整数和数组溢出,产生无意义的结果,所以如果你选择使用它,你必须保证自己在你的程序中不可能发生溢出.

Keep in mind that -Ofast is comes with risks. e.g. It will silently ignore integer and array overflows, producing nonsense results, so if you choose to use it you'll have to guarantee yourself that overflows aren't possible in your program.

这篇关于Swift 处理数字真的很慢吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆