2016-07-20 16 views
1

Zunächst einmal entschuldige ich mich für eine solche Anfängerfrage. Mein Ziel ist nicht nur eine Chi-Quadrat-Funktion zu erstellen, sondern zu verstehen, wie das allgemeine Problem vermieden werden kann.Erstellen einer Chi-Quadrat-Funktion in Lisp. [Anfänger]

Mein Code sieht wie folgt aus:

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

Die dritte Bedingung in Ordnung arbeitet wie ich glaube, es sei denn, es nennt Chi-Quadrat auf Null und Null der Ausgang nur liest 0. Ich verstehe, warum dies geschieht (wegen der zweiten Bedingung), aber ich weiß nicht, wie ich es vermeiden kann. Wenn ich zum Beispiel eine Erwartungsliste von (100 50) und eine Beobachtungsliste von (90 60) gebe, möchte ich, dass sie (+ 1 (+ 2 0)) = 3 ausgibt. Wie kann ich (Chi-Quadrat nil nil) ein Wert von 0 ohne nur die Funktion zu beenden, dann und dort?

Haftungsausschluss: Ich bin sicher, es gibt bessere Möglichkeiten, dies zu tun, und vielleicht Funktionen, die das bereits tun. Ich schreibe diese Funktion nur zu Lernzwecken.

Antwort

3

Es ist ein Fehler in dem dritten cond Fall: t vor der Summe fehlen:

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

Sie die Syntax des cond Makro in den specification finden.

+0

Vielen Dank, dass Sie sich die Zeit nehmen, um meine Frage zu beantworten. Das hat mein Problem gelöst. –

0

Im Allgemeinen möchten Sie vermeiden, etwas wie length innerhalb der Prozedur aufzurufen, in der Sie die gleiche Liste wiederholen. Das liegt daran, dass die Laufzeit von length proportional zur Länge der Liste ist, die Sie ihm geben, und Sie werden mit einem O (N^2) -Algorithmus enden, weil Sie ihn auf jedem Ende der ursprünglichen Liste aufrufen. Was ist in Ordnung, wenn Ihre Liste immer kurz ist? Besser, die Listenlängen nur einmal zu Beginn der Routine zu testen, oder am Ende zu retten, wenn eine der Listen null ist und die andere nicht. Wie auch immer, hier sind ein paar andere Möglichkeiten, diese Funktion zu schreiben:

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