1

我正在尝试编写一个可以计算 GPA 的函数。现在我可以进行有限的计算(只有 3 个),但我坚持如何计算更多,而不使用循环或递归(这是主题的要求)如何扩展第 n 个函数?比如:(nth n),如果是这样,这是否意味着我需要编写一个 lambda 表达式?作为一个新手,我可能无法清楚地描述这个问题,真的需要一些帮助..

Glist是成绩点Clist是学分。

GPA=(gradepoint *credithour +gradepoint *credithour) / (credithour之和) 如:(3*1+3*2+4*1)/(1+2+1)

这是我的代码:

(defun gpa (Glist Clist)
     (format t "~3,2f~%" 
      (/ 
        (+(nth 0 (mapcar #' * Glist Clist))
          (nth 1 (mapcar #' * Glist Clist))
          (nth 2 (mapcar #' * Glist Clist)))
        (+ (nth 0 Clist)
           (nth 1 Clist)
           (nth 2 Clist))
                   );end "/"
                   );end "format" 
       (values)    );end 
4

2 回答 2

7

编辑

这似乎是一个很好的机会来强调一些常见的(小 c)Lisp 想法,所以我充实了我的答案来说明。


正如另一个答案中提到的,您可以使用sum对列表(数字)进行操作的函数:

(defun sum (nums)
  (reduce #'+ nums))

点积是两个(等长)向量的乘积:

(defun dot-product (x y)
  (sum (mapcar #'* x y)))

该函数gpa是两者的简单组合:

(defun gpa (grades credits)
  (/ (dot-product grades credits) (sum credits)))

问题中的示例得到了我们期望的答案(减去被格式化为浮点数):

(gpa '(3 3 4) '(1 2 1))
> 13/4

这个例子有几点值得一提:

  1. 您应该了解map,reduce及其变体和亲属。这些函数对 Lisp 非常重要,对于列表操作非常有用。 map*函数通常将序列映射到序列,并且reduce通常将序列转换为单个值(但是您可以使用类似的形式(reduce #'cons '(1 2 3)))。

  2. 这是“自下而上”编程方法的一个很好的例子;sum通过编写通常有用的简单函数,您可以轻松地在其上编写代码dot-product。现在该gpa函数是建立在其他两个之上的简单易读的函数。这些都是单行的,对于任何具有 CL 基本知识的人来说都很容易阅读。这与通常应用于 OOP 的方法形成对比。

  3. 没有重复的代码。当然,sum不止一次使用,但只在有意义的地方使用。您可以做更多的事情来抽象列表元素总和的概念。在 Scheme 中用函数编写函数更自然,这是一个完全不同的话题。这是一个简单的例子,但没有两个函数在做同样的事情。

于 2011-09-09T05:00:59.163 回答
1

如果你nth用来遍历一个列表,那么你做错了。在这种情况下,您可能需要编写一个求和函数:

(defun sum (items)
  (reduce #'+ items))
于 2011-09-09T03:45:39.617 回答