Ist dies eine angemessene Umsetzung der quadratischen Bézier-Funktion in OCaml?
Frage
Ein Freund kam in einer quadratischen Bézier-Kurven-Funktion in seiner Code-Basis, die eine gigantische Rattennest eines Schalter Tabelle verwendet, um die Berechnung durchzuführen. Er forderte mich auf einen einzigen, kurzen Ausdruck zu finden, die ihm den riesigen Block von Code zu ersetzen erlauben würde.
Bei dem Versuch, zwei verschiedene Kuriositäten gerecht zu werden, dachte ich, ich würde versuchen, die Funktion in OCaml implementieren. Ich bin ein sehr Anfänger OCaml Programmierer und ich bin auch nicht vertraut mit der Funktion und diesem spezifischen Implementierung ist schwer über Google zu bekommen.
Critiques auf, sowohl die Performance / Richtigkeit der Funktion sowie deren Umsetzung sind sehr geschätzt.
Die Umsetzung der quadratische Bézierkurve :
let rec b2 n =
let p1 = -10. in
let p2 = 10. in
let q = n*.n in
let rec b2i n i hd =
if i > n then
List.rev hd
else
let t = i /. n in
b2i n (i+.1.) ((((1.-.t)**2.)*.p1+.(2.*.t*.(1.-.t)*.q)+.(t**2.)*.p2) :: hd)
in b2i n 0. []
;;
let floatprint lst = List.iter (fun f -> Printf.printf "%f; " f) lst ;;
floatprint (b2 8.);;
Lösung
b2 ist nicht rekursiv, so dass keine Notwendigkeit für [rec lassen b2 n =]. Da n ändert sich nie, keine Notwendigkeit, es als Argument müssen B2I, nur n aus dem umschließenden Bereich zu verwenden. Ihre innere Funktion auf p0, p1 und p2 abhängen sollte, aber ich sehe es in Abhängigkeit von -10, n ** 2 und 10. Die Funktion hat auch die Form einer Karte von [0.0. 1,0; 2,0; ...; n.0] auf die endgültigen Werte. Könnten Sie es schreiben:
let b i =
let t = i /. n in
let tminus = (1.-.t) in
(tminus *. tminus *. p0) +. (2. *. t *. tminus *. p1) +. (t *. t * p2)
in
List.map b ([generate list 1.0; 2.0; ... n.0])
Eine Funktion die Liste 1.0 zu generieren ... n.0 sein könnte: (für kleine n)
let rec count m n = if m > n then [] else m :: (count (m+.1.) n)
Andere Tipps
Ich habe zwei Vorschläge:
Sie sollten List.rev
rufen nach b2i
kehrt so kann ocaml ausnutzen es ist Schwanz-Rekursion Optimierungen. Ich bin nicht sicher, wie gut ocaml mit der aktuellen Implementierung befassen wird, List.rev
ist Schwanz-rekursive though. Sie werden bemerken, dass in diesen Beitrag es gemacht wird wie das.
Sie können aber auch die Auflösung der Iteration machen ein optionales Argument wie ?(epsilon=0.1)
sein.
Als ocaml Programmierer ich viel falsch nicht beiseite sehen hier aus, dass --as solange P1 und P2 in der Tat Konstanten sind. Kompilieren Sie es nach unten und sehen, was der Unterschied in der Montage ist List.rev zwischen sich bewegenden innen oder aus dem Schwanz-Rekursion.
Dies kann picayune, aber hd
ist kein guter Name für einen Listenparameter. List.hd
ist eine Standardfunktion, die das erste Element einer Liste zurück. Mit hd
als Name für eine Liste zu Verwirrung führen.