Разумная ли это реализация квадратичной функции Безье в OCaml?

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

  •  02-07-2019
  •  | 
  •  

Вопрос

Друг наткнулся в своей кодовой базе на квадратичную функцию кривой Безье, которая использовала для выполнения вычислений гигантское крысиное гнездо таблицы переключателей.Он предложил мне найти одно короткое выражение, которое позволило бы ему заменить гигантский блок кода.

Пытаясь удовлетворить два разных любопытства, я решил попробовать реализовать эту функцию в OCaml.Я очень начинающий программист OCaml, и я также не знаком с этой функцией и этим специфический реализацию трудно найти через Google.

Критика как по производительности/правильности функции, так и по ее реализации очень приветствуется.

Реализация Квадратичная кривая Безье:

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.);;
Это было полезно?

Решение

b2 не является рекурсивным, поэтому нет необходимости в [let Rec b2 n =].Поскольку n никогда не меняется, нет необходимости использовать его в качестве аргумента для b2i, просто используйте n из охватывающей области.Ваша внутренняя функция должна зависеть от p0, p1 и p2, но я вижу ее в зависимости от -10., n**2 и 10.Функция также имеет вид карты из [ 0.0;1,0;2,0;...;n.0] до окончательных значений.Не могли бы вы написать это:

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

Функция для создания списка 1.0...n.0 может быть такой:(для маленького n)

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

Другие советы

У меня есть два предложения:

Вам следует позвонить List.rev после b2i возвращает, чтобы ocaml мог использовать оптимизацию хвостовой рекурсии.Я не уверен, насколько хорошо ocaml справится с текущей реализацией. List.rev однако является хвостовой рекурсией.Вы заметите, что в эта почта это делается так.

Кроме того, вы можете сделать разрешение итерации необязательным аргументом, например ?(epsilon=0.1).

Как программист ocaml, я не вижу в этом ничего плохого, кроме этого, поскольку P1 и P2 на самом деле являются константами.Скомпилируйте его и посмотрите, в чем разница в сборке между перемещением List.rev внутрь хвостовой рекурсии или из нее.

Возможно, это мелочь, но hd это неподходящее имя для параметра списка. List.hd — стандартная функция, возвращающая первый элемент списка.С использованием hd в качестве названия списка приведет к путанице.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top