Swift でエラトステネスの篩

こんな感じ。
eratosthenes.swift

func eratosthenes(_ n: Int) -> [Int] {
    var ar = Array(0...n)
    for i in 2...Int(sqrt(Double(n))) {
        if ar[i] == 0 {continue}
        for j in 2...(n / i) {ar[i * j] = 0}
    }
    return ar.filter {$0 != 0}
}

print(eratosthenes(1000))

 
1000万までの素数を求めてみました(出力はしていません)。Swift 4.0, Linux Mint 18.2。

$ time ./eratosthenes

real	0m6.161s
user	0m6.108s
sys	0m0.052s

6秒もかかっていますね。Ruby版よりも遅いですよ? Ruby版の倍も時間がかかっています。どういうこと? アルゴリズムRuby と同じです。なお、インタプリタで実行しても時間はほとんど変わりません。何かおかしいですね。

ちなみに C言語だとこの 1/10 の時間しかかかりません。


※追記
遅い理由がわかりました。Swift の Array はそのままでは遅いらしいです。コンパイル時に -O オプションを付けて最適化してやる必要があります。

$ swiftc eratosthenes.swift -O
$ time ./eratosthenes

real	0m0.234s
user	0m0.196s
sys	0m0.016s

今度は C言語よりも速くなりました! しかしあまりにも数値がちがいすぎますね。