Box Generator / Sprache Haskell
 
StartSeite | BoxGenerator/ | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern

Hier ein Beispiel mehr dafür, dass man sich in Haskell im allgemeinen recht kurz fässt. Das alles passiert ohne Iteratoren, explizite Speicherverwaltung, Klassenhierarchien und so weiter. Alles was wir brauchen sind Funktionen und die verzögerte Auswertung.

module RndBox where

import Random(Random,RandomGen,randomRs)

norm2sqr :: Num a => (a,a) -> a
norm2sqr (x,y) = x^2 + y^2

normalDist :: Floating a => ((a,a),a) -> (a,a)
normalDist ((x,y),norm) =
   let p = sqrt (-2 * log norm) / norm
   in  (p*x, p*y)

bundlePairs :: [a] -> [(a,a)]
bundlePairs (x:y:ss) = (x,y) : bundlePairs ss
bundlePairs (_:_)    = error "Odd number of figures."
bundlePairs []       = []

resolvePairs :: [(a,a)] -> [a]
resolvePairs = concatMap (\(x,y)->[x,y])

randomGaussians :: (Random a, Ord a, Floating a, RandomGen g) => g -> [a]
randomGaussians =
   resolvePairs . map normalDist . filter ((<=1) . snd) .
      map (\p -> (p, norm2sqr p)) . bundlePairs . randomRs (-1,1)

Das letzte ist die Hauptfunktion, welche man von hinten nach vorne lesen kann: Erzeuge mit Hilfe eines Zufallsgenerators eine unendliche Liste von (-1,1)-gleichverteilten Zufallszahlen (randomRs), wandele sie in eine Liste von Paaren um (bundlePairs), bestimme zu jedem Punkt den quadrierten Abstand vom Kreismittelpunkt (map (\p -> (p, norm2sqr p))) und beachte nur die Zahlen, die im Kreis liegen (filter <=1) . snd, wandele die Punkte in normalverteilte Größen um (normalDist) und reihe die Zahlenpaare wieder in eine Liste von Zahlen ein (resolvePairs).

Wir arbeiten die ganze Zeit formal mit unendlichen Listen, aber die verzögerte Auswertung kümmert sich nur um die Werte, die wirklich gebraucht werden, und das sind immer nur endlich viele. Wir müssen im wesentlichen nur aufschreiben, was wir machen wollen, aber wir können viele Details weglassen, darüber wie wir es machen wollen. Wenn wir beispielsweise den ersten Wert von randomGaussians abfragen, werden automatisch zwei Zufallszahlen generiert, diese zu einem Paar zusammengefasst, das Zahlenpaar wie gewünscht verarbeitet und nur die erste Zahl wird ausgegeben. Wenn wir die zweite Zahl abfragen, wird nur noch (p*y) in normalDist berechnet.

Der Box-Müller-Generator ist bereits in der HaskellDSP?-Bibliothek verewigt.

  http://haskelldsp.sourceforge.net/doc/Numeric.Random.Distribution.Normal.html#normal_bm


StartSeite | BoxGenerator/ | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Text dieser Seite ändern (zuletzt geändert: 6. März 2006 11:25 (diff))
Suchbegriff: gesucht wird
im Titel
im Text