最近在学习Autolisp编程,程序中用到了矩阵运算,如果像C语言(或C++)语言编程那样一个个处理矩阵中的元素,那程序要写很长,而且很容易出错。在论坛中,网上搜索发现,mapcar、lambda和apply三个函数用好了,对矩阵运算非常方便。于是查手册,看看三个函数的用法:
Apply: (apply 'function list)
将参数表传给指定的函数
参数:
' function ——函数,可以是表示defun或lambda表达式的符号。
list ——表。如果函数不接收参数,则该参数为nil。
返回值:
函数调用的结果。---------注意该函数返回值为一个值,数值、字符串等。
例如: (apply '+ '(1 2 3)) 结果为 6
这个函数看似不难用,理解也比较容易。
Mapcar:(mapcar function list1 ……listn)
将作为本函数参数的一个或多个表的各个元素提供给指定函数进行求值,并将由求值结果构成的表返回。
参数:
function ——函数。
list1……listn——一个或多个表。
返回值:
表。--------注意返回值是一个表。
例如:(mapcar '1+ '(10 11 12)) 结果为 (11 12 13)
这个函数看起来也不难理解,注意返回结果为表就行了。
再看第三个——
Lambda:(lambda arguments expr……)
在经常使用某一个表达式,而又觉得把它定义成一个新函数开销太大时,可以使用lambda函数。lambda将定义的函数放在要使用它的位置,还可以使程序员的意图表达得更清楚。lambda函数返回它最后一个expr的值。它常与apply和(或)mapcar函数连用,以便对表中的元素执行某个运算。
参数:
argument——传给表达式的参数
expr ——Autolisp表达式。
返回值
最后一个expr的值。
这个函数光看这个解释有点不知所云了,还是看个例子吧。
例如:(apply '(lambda ( x y z) (* x (- y z))) '(5 20 14)) 结果 30
能不能看出来函数是如何计算的? 5*(20-14)=30。其中 (lambda ( x y z) (* x (- y z))) 是定义的无名函数, 也就是apply函数的第一个参数,'(5 20 14 )apply的第二个参数表。这么一拆分也就理解了。
好了,熟悉了三个函数的使用方法,回到正题。如何在矩阵运算中应用这三个函数呢,能怎么帮我们简化代码呢?!
在Lee Mac Programming: Custom Programs for AutoCAD找到了这样一段代码:
;; Matrix x Vector - Vladimir Nesterovsky
;; Args: m - nxn matrix, v - vector in R^n
(defun mxv ( m v )
(mapcar '(lambda ( r ) (apply '+ (mapcar '* r v))) m)
)
功能是求n阶方阵和n维列向量的乘法,代码太简洁了。
不知道你是不是看懂了函数是如何运算的,把它分解一下(mapcar '(……) m),其中'(……)是无名函数,他要对表m的每一个元素进行计算,m的元素是什么?n维向量!
再看看这个无名函数(lambda (r) (……))其中参数r是什么?对!m的每一个元素。
(……)这个运算是什么呢?(apply ‘+ (mapcar ’* r v)) r中每个元素和v中每个元素相乘的形成的表再求和。
最后的结果是什么?mapcar在最外层,肯定是个表,对了,n维向量!不知道你看明白了没有。
好了,我的程序中要求矩阵的特征值和特征向量。计算过程中用到了协方差的计算,涉及到了m×n维矩阵与m维向量的乘法,m×n维矩阵与n×m维矩阵的运算,下面把我写的代码发一下,大家慢慢理解吧:
(setq lst (mapcar '(lambda (c) (mapcar '(lambda (r) (apply '+ (mapcar '* r c))) matrix)) matrix))
其中:matrix是m×n阶矩阵,结果是n×n阶方阵,赋值给lst。
(setq covMx (mapcar '(lambda (r) (mapcar '(lambda (x) (/ x num)) r)) lst))
将上一步计算所得的方阵每个元素都除以num(一个数)。
希望我的代码能帮到你!
3855

被折叠的 条评论
为什么被折叠?



