Mein ursprüngliches Ziel beim Verfassen dieses Artikels war es, einen möglichst kleinen Fußabdruck zu hinterlassen. Ich kann mit Sicherheit sagen, dass ich dieses Ziel erreicht habe. Leider führt dies zu einer recht langsamen Implementierung. Um alle Primzahlen unter 2 Millionen zu generieren, braucht man auf einem 3Ghz Intel Chip etwa 8 Sekunden.
Gibt es eine Möglichkeit, die Ausführungszeit dieses Codes zu verbessern, ohne den geringen Speicherbedarf zu beeinträchtigen? Oder gehe ich von einem funktionalen Standpunkt aus betrachtet die Sache falsch an?
CODE
/// 6.5s for max = 2,000,000
let generatePrimeNumbers max =
let rec generate number numberSequence =
if number * number > max then numberSequence else
let filteredNumbers = numberSequence |> Seq.filter (fun v -> v = number || v % number <> 0L)
let newNumberSequence = seq { for i in filteredNumbers -> i }
let newNumber = newNumberSequence |> Seq.find (fun x -> x > number)
generate newNumber newNumberSequence
generate 2L (seq { for i in 2L..max -> i })
Update
Ich habe den Algorithmus optimiert und konnte so 2 Sekunden einsparen, aber den Speicherverbrauch verdoppeln.
/// 5.2s for max = 2,000,000
let generatePrimeNumbers max =
let rec generate number numberSequence =
if number * number > max then numberSequence else
let filteredNumbers = numberSequence |> Seq.filter (fun v -> v = number || v % number <> 0L) |> Seq.toArray |> Array.toSeq
let newNumber = filteredNumbers |> Seq.find (fun v -> v > number)
generate newNumber filteredNumbers
generate 2L (seq { for i in 2L..max -> i })
Update
Offenbar habe ich einen alten Compiler verwendet. Mit der neuesten Version benötigt mein ursprünglicher Algorithmus 6,5s statt 8s. Das ist eine ziemliche Verbesserung.