Si tratta di un'implementazione ragionevole della funzione quadratica di Bézier in OCaml?

StackOverflow https://stackoverflow.com/questions/145056

  •  02-07-2019
  •  | 
  •  

Domanda

Un amico si imbatté in una funzione quadratica B & # 233; zier curve nella sua base di codice che utilizzava un gigantesco ratto nido di una tabella di switch per eseguire il calcolo. Mi ha sfidato a trovare un'unica, breve espressione che gli avrebbe permesso di sostituire il gigantesco blocco di codice.

Nel tentativo di soddisfare due diverse curiosità, ho pensato di provare a implementare la funzione in OCaml. Sono un programmatore OCaml molto alle prime armi e non ho familiarità con la funzione e questa implementazione specifica è difficile da trovare tramite Google.

Sono molto apprezzate le critiche su prestazioni / correttezza della funzione e sulla sua implementazione.

Implementazione di Quadratic B & # 233; zier Curve :

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.);;
È stato utile?

Soluzione

b2 non è ricorsivo, quindi non è necessario [let rec b2 n =]. Poiché n non cambia mai, non è necessario averlo come argomento per b2i, basta usare n dall'ambito che lo racchiude. La tua funzione interna dovrebbe dipendere da p0, p1 e p2, ma la vedo in base a -10., N ** 2 e 10. La funzione ha anche la forma di una mappa da [0,0; 1.0; 2.0; ...; n.0] ai valori finali. Potresti scriverlo:

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])

Una funzione per generare l'elenco 1.0 ... n.0 potrebbe essere: (per la piccola n)

let rec count m n = if m > n then [] else m :: (count (m+.1.) n)

Altri suggerimenti

Ho due suggerimenti:

Dovresti chiamare List.rev dopo i ritorni di b2i in modo che ocaml possa sfruttare le sue ottimizzazioni di ricorsione della coda. Non sono sicuro di quanto bene Ocaml gestirà l'attuale implementazione, List.rev è comunque ricorsivo. Noterai che in questo post è fatto come che.

Inoltre, puoi rendere la risoluzione dell'iterazione un argomento facoltativo come ? (epsilon = 0.1) .

Come programmatore ocaml non vedo molto male qui a parte questo - fintanto che P1 e P2 sono in realtà costanti. Compilalo verso il basso e vedi qual è la differenza nell'assemblaggio tra spostare List.rev all'interno o all'esterno della ricorsione della coda.

Potrebbe essere Picayune, ma hd non è un buon nome per un parametro di elenco. List.hd è una funzione standard che restituisce il primo elemento di un elenco. L'uso di hd come nome per un elenco genererà confusione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top