이것은 OCAML에서 2 차 베지어 함수의 합리적인 구현입니까?

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

  •  02-07-2019
  •  | 
  •  

문제

친구가 코드베이스에서 2 차 베지어 곡선 기능을 발견하여 스위치 테이블의 거대한 쥐 둥지를 사용하여 계산을 수행했습니다. 그는 저에게 거대한 코드 블록을 대체 할 수있는 단일의 짧은 표현을 찾도록 도전했습니다.

두 가지 다른 호기심을 만족시키기 위해 OCAML에서 함수를 구현하려고 시도했다고 생각했습니다. 나는 매우 초보자 OCAML 프로그래머이고 또한 그 기능에 익숙하지 않습니다. 특정한 구현은 Google을 통해 오기가 어렵습니다.

기능의 성능/정확성과 구현에 대한 비판은 대단히 감사합니다.

구현 2 차 베지어 곡선:

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는 재귀가 아니므로 [rec b2 n =]가 필요하지 않습니다. n은 절대 변하지 않기 때문에 B2I에 대한 인수로 가질 필요가 없으며, Enclosing 범위에서 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은 다음과 같습니다.

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가 실제로 상수 인 한 그 외에는 별다른 잘못을 보지 못합니다. 그것을 아래로 컴파일하고 조립의 차이가 움직이는 목록 사이에 무엇이 있는지 확인하십시오.

이것은 picayune 일 수 있지만 hd 목록 매개 변수의 좋은 이름이 아닙니다. List.hd 목록의 첫 번째 요소를 반환하는 표준 함수입니다. 사용 hd 목록의 이름으로 혼란을 초래할 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top