方案标准偏差

时间:2018-04-17 22:26:12

标签: scheme racket

我正在尝试获取一个返回单个列表标准偏差的函数,我的代码运行得很好,但我想学习如何使用map,apply和filter来应用此代码。到目前为止,我已经使用了普通函数的应用程序,但我无法在其余的代码中使用它们

(define (average li)
  (/ (apply + li) (length li)))

(define (summation li avg)
  (if (null? li)
    0
    (+  
       (* (- (car li) avg) 
          (- (car li) avg))
    (summation (cdr li) avg))))

(define (sd li)
    (sqrt
        (/  
          (summation li (average li))
          (- (length li) 1))))

我觉得地图可以在求和函数中使用,但它会犯一个大错误。

1 个答案:

答案 0 :(得分:2)

您可以使用foldl

表达summation
(define (summation li avg)
  (foldl (lambda (x acc)
           (+ acc
              (expt (- x avg)
                    2)))
         0
         li))

虽然这里提供的这些程序看似简单,但您应该考虑其实施的后果。例如,我确定您可以编写自己的length函数

(define (length li)
  (if (null? li)
      0
      (+ 1 (length (cdr li)))))

您使用(apply + li)来计算输入列表的总和,但我确信您已经意识到这是我们简单的递归解决方案的明智替代

(define (sum li)
  (if (null? li)
      0
      (+ (car li)
         (sum (cdr li)))))

鉴于sumlength,我们实施了average

(define (average li)
  (/ (sum li)
     (length li)))

你在这看到问题吗? sumlength都遍历输入列表。然后我们继续写sd ...

(define (sd li)
  (sqrt (/ (summation li
                      (average li))
           (- (length li) 
              1))))

你看到问题是如何恶化的吗?我们知道average已逐步完成输入列表li两次,summation逐步完成再次,并注意到另一个 em>致电length - 我们已经li 4 次重复,sd可以返回结果

让我们回顾一下。看average,如果我们可以通过某种方式将li 的元素同时计算在内,那会不会很好?好吧,我们可以!

(define (average li (return /))
  (if (null? li)
      (return 0 0)
      (average (cdr li)
               (lambda (sum count)
                 (return (+ sum (car li))
                         (+ count 1))))))


(average '(1))     ;; 1
(average '(1 2))   ;; 1 1/2
(average '(1 2 3)) ;; 2
(average '())      ;; Error: division by zero

使用此技术,您几乎可以执行任何复杂的转换。使用这种风格写sd留给读者练习。