我正在寻找有关如何将两个多项式列表相乘的提示,例如如何创建函数 (poly_mul'(3 4 5)'(5 9 6 2))输出应为(15 47 79 75 38 10)
我到目前为止所拥有的:
(define (poly-mul lst1 lst2)
(let loop ((expo 0) (l1 lst1) (l2 lst2))
(cond ((null? l1) '())
((null? l2) (loop expo (cdr l1) lst2))
(else (cons (* (car l1) (car l2))
(loop expo l1 (cdr l2)))))))
答案 0 :(得分:1)
您可以将poly-mult
视为递归poly-add
。鉴于易于实现的poly-add
。
(define (poly-add p1 p2)
(cond ((empty? p1)
p2)
((empty? p2)
p1)
(else
(cons (+ (car p1)
(car p2))
(poly-add (cdr p1)
(cdr p2))))))
您可以使用poly-mult
帮助程序来实现raise
。
(define (poly-mul p1 p2 (e 0))
(if (empty? p1)
empty
(poly-add (raise e (map (curry * (car p1)) p2))
(poly-mul (cdr p1)
p2
(+ e 1)))))
(define (raise e p)
(if (= e 0)
p
(cons 0
(raise (- e 1)
p))))
(poly-mul '(3 4 5) '(5 9 6 2))
;; '(15 47 79 75 38 10)
通过将raise
定义为外部过程,很容易看出我们如何将多项式提高到下一个幂。但是,我们可以通过使用循环并将指数(poly-mult
)用作函数本身来将这种行为包含在e
内部。
(define (poly-mul p1 p2)
(let loop ((p p1) ;; polynomial
(e identity)) ;; exponent
(if (empty? p)
empty
(poly-add (e (map (curry * (car p)) p2))
(loop (cdr p)
(compose (curry cons 0) e))))))
(poly-mul '(3 4 5) '(5 9 6 2))
;; '(15 47 79 75 38 10)
最后,在poly-mult
中使用循环使我们很容易将递归调用转换为适当的尾调用。现在首先进行poly-add
操作,并将更新的累加器(acc
)分配给下一个循环迭代。
(define (poly-mul p1 p2)
(let loop ((acc empty) ;; accumulator
(p p1) ;; polynomial
(e identity)) ;; exponent
(if (empty? p)
acc
(loop (poly-add acc
(e (map (curry * (car p)) p2)))
(cdr p)
(compose (curry cons 0) e)))))
答案 1 :(得分:0)
您找到了一种将数字相乘的方法。现在,您需要像平时在纸上那样添加带有移位索引的文件:
15 27 18 06 00 00
00 20 36 24 08 00
00 00 25 45 30 10
使用向量将更容易,例如,使用列表求和时附加零:
(define polynomial-mul
(lambda (lst1 lst2)
(let ((tmp
(map (lambda (n)
(map (lambda (m)
(* n m))
lst2)) lst1)))
(let loop ((z '(0)) (l (car tmp)) (r (cdr tmp)))
(cond
((null? r) l)
(else
(loop (cons 0 z)
(map +
(append l '(0))
(append z (car r)))
(cdr r))))))))
但是由于添加,这是非常低效的。最好使用辅助功能来移动两个列表:
(define shifted-map
(lambda (f shift lst1 lst2)
(cond
((and (not (null? lst1)) (not (zero? shift)))
(cons (car lst1)
(shifted-map f (sub1 shift) (cdr lst1) lst2)))
((null? lst2) lst1)
(else
(cons (f (car lst1) (car lst2))
(shifted-map f shift (cdr lst1) (cdr lst2)))))))
(define polynomial-mul
(lambda (lst1 lst2)
(let ((tmp
(map (lambda (n)
(map (lambda (m)
(* n m))
lst2)) lst1)))
(let loop ((shift 1) (l (car tmp)) (r (cdr tmp)))
(cond
((null? r) l)
(else
(loop
(add1 shift)
(shifted-map + shift l (car r))
(cdr r))))))))
答案 2 :(得分:0)
使用SRFI-1的fold-right
,它就像从中学数学中一样,是一个从右到右的缩放和加法循环:
(require srfi/1)
(define (multpoly p1 p2)
(fold-right
(lambda (a r)
(addpoly (map (lambda (b) (* a b)) p2) ; map (a*) p
(cons 0 r)))
'() p1))
其中
(define (addpoly p1 p2)
(cond ((null? p1) p2)
((null? p2) p1)
(else (cons (+ (car p1) (car p2))
(addpoly (cdr p1) (cdr p2))))))