É este uma implementação razoável da função Bézier quadrática em OCaml?

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

  •  02-07-2019
  •  | 
  •  

Pergunta

Um amigo veio através de uma função de curva Bézier quadrática em sua base de código que usou uma ratos gigantesco ninho de uma mesa interruptor para executar o cálculo. Ele desafiou-me a encontrar uma única expressão, curta que permitiria a ele para substituir o bloco gigantesco de código.

Na tentativa de satisfazer duas curiosidades diferentes, eu pensei que eu ia tentar implementar a função em OCaml. Eu sou um muito novato programador OCaml e eu também estou familiarizado com a função e este específica implementação é difícil passar por aqui via Google.

As críticas, tanto da função performance / correção, bem como a sua implementação são muito apreciado.

quadrática Bé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.);;
Foi útil?

Solução

b2 não é recursivo, assim não há necessidade para [deixar b2 rec n =]. Desde n nunca muda, não há necessidade de tê-lo como argumento para B2I, basta usar n do âmbito de inclusão. Sua função interna deve depender P0, P1 e P2, mas eu vejo isso dependendo -10, n ** 2 e 10. A função também tem a forma de um mapa de [0.0.; 1,0; 2,0; ...; n.0] para os valores finais. você poderia escrevê-lo:

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

Uma função para gerar a lista 1.0 ... n.0 poderia ser: (para pequenas n)

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

Outras dicas

Eu tenho duas sugestões:

Você deve chamar List.rev após b2i retornos tão ocaml pode explorá-la de otimizações cauda-recursão. Não estou certo de quão bem ocaml vai lidar com a implementação atual, List.rev é, porém cauda-recursivo. Você vai notar que em este post é feito como isso.

Além disso, você pode fazer a resolução da iteração ser um argumento opcional como ?(epsilon=0.1).

Como um programador ocaml eu não vejo muito errado aqui além de que --como desde que P1 e P2 estão em constantes fatos. Compilá-lo para baixo e ver o que a diferença de montagem é entre mover List.rev dentro ou para fora da cauda-recursão.

Isto pode ser picuinhas, mas hd não é um nome bom para um parâmetro lista. List.hd é uma função padrão que retorna o primeiro elemento de uma lista. Usando hd como um nome para a lista vai levar a confusão.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top