2016-07-20 3 views
1

먼저 초급 질문에 사과드립니다. 내 목표는 카이 제곱 함수를 만드는 것이 아니라 내가 경험하고있는 일반적인 문제를 피하는 방법을 이해하는 것입니다.lisp에서 카이 제곱 함수 만들기. [초급]

내 코드는 다음과 같습니다 단지 왜 이런 일 0을 이해 읽기가 전무에 출력 전무 카이 제곱 호출 할 때를 제외하고 세 번째 조건이 제대로 작동

(defun chi-square (expected-list observed-list) 
(cond ((not (= (length expected-list) (length observed-list))) (print "Lists do not match in length.~%")) 
    ((and (null expected-list) (null observed-list)) 0) 
    (+ (/ (square (- (car observed-list) (car expected-list))) (car expected-list)) 
     (chi-square (cdr expected-list) (cdr observed-list))) 
) 
) 

내가 생각 (두 번째 조건 때문에),하지만 나는 그것을 피하는 방법을 모른다. 예를 들어, (100 50)의 기대 목록과 (90 60)의 관측 목록을 주면 출력 할 수 있습니다 (+ 1 (+ 2 0)) = 3. 어떻게 할 수 있습니까? (chi-square nil nil) 0의 값은 함수를 끝내지 않고 바로 끝낼 수 있습니까?

고지 사항 :이 작업을 수행하는 데 더 좋은 방법이있을 것이며, 이미이 작업을 수행하고있는 기능 일 수 있습니다. 나는 학습 목적으로 만이 함수를 작성하고있다.

답변

3

세 번째 cond 경우에 오류가 있습니다 : t는 합계 전에 누락되었습니다

(defun chi-square (expected-list observed-list) 
    (cond ((not (= (length expected-list) (length observed-list))) 
     (print "Lists do not match in length.~%")) 
     ((and (null expected-list) (null observed-list)) 0) 
     (t (+ (/ (square (- (car observed-list) (car expected-list))) (car expected-list)) 
       (chi-square (cdr expected-list) (cdr observed-list)))))) 

당신은 specificationcond 매크로의 구문을 찾을 수 있습니다.

+0

제 질문에 답변 해 주셔서 감사합니다. 이것은 내 문제를 해결했다. –

0

일반적으로 동일한 목록을 재귀하는 절차에서 length과 같은 것을 사용하지 않는 것이 좋습니다. 그 이유는 실행 시간이 length이기 때문에 목록의 길이에 비례하기 때문입니다. 원본 목록의 꼬리마다 호출하므로 O (N^2) 알고리즘으로 끝납니다. 당신의 목록이 항상 짧다면 괜찮습니다. 루틴이 시작될 때 목록 길이를 한 번만 테스트하는 것이 더 좋으며, 목록 중 하나가 null이고 다른 하나가 그렇지 않을 때 끝날 때까지 구제 조치를하는 것이 좋습니다. 어쨌든,이 함수를 작성하는 다른 방법은 다음과 같습니다.

;using built-in recursion combinators (mapcar & reduce) 
(defun χ² (expected observed) 
    (reduce #'+ (mapcar (lambda (e o) (/ (square (- o e)) e)) expected observed))) 

;using loop 
(defun chi-sqr (expected observed) 
    (loop 
    for e in expected 
    for o in observed 
    summing (/ (square (- o e)) e))) 
관련 문제