Scheme 4 Javaer-7.符号数据

SICP有个缺点:不利于我们跳读。

当我想忽略或快速浏览某些章节后,阅读《2.3符号数据》,又逼得我不得不回头找一下某些东西。

例如

练习2.53中提到的cadr,我得回头查一查;

练习2.54中,如何判断表的一个元素是否表,是否符号?我不会耶!!!2.3.2中提到判断表达式是否数值的基本函数number?,应该有相关的基本过程吧,那里提到了呢?晕,在<代数表达式的表示>中提到了symbol?,

还能不能让我好好玩耍?


本节对我们应该有点吸引力,因为在《编程导论(Java)•0.1.1 计算简史*》中提到:“莱布尼茨的梦想:符号可以像数字一样进行推导和演算。这就是符号系统的计算!”但是《编程导论(Java)》并没有涉及这一部分(如多项式)。

符号求导对于Lisp有着特殊的历史意义,也是符号计算(symbolic computation)的经典例子。例如ax2 +bxy+z表达式对x求导,将获得2ax+by。SICP给出了计算+和*构成的表达式的求导程序。

1.被求导的表达式,按照前缀形式表示。练习2.58要求完成中缀表示,但是会有更多的困难,如省略的括号和优先级问题。

2.前缀表示时的基本函数:需要提取被求导的表达式的各个符号(求和式子、求积式子、常量、变量),将结果组合成表达式。

;x是变量?
(define (variable? x) (symbol? x))
;
(define (same-variable? v1 v2) 
  (and (variable? v1) (variable? v2) (eq? v1 v2)))
;
(define (make-sum a1 a2) (list '+ a1 a2))
(define (make-product m1 m2) (list '* m1 m2))

(define (sum? x)
  (and (pair? x) (eq? (car x) '+)))
(define (addend s) (cadr s))
(define (augend s) (caddr s))
(define (product? x)
  (and (pair? x) (eq? (car x) '*)))
(define (multiplier p) (cadr p))
(define (multiplicand p) (caddr p))
3.求导函数

(define (deriv exp var)
  (cond ((number? exp) 0)
        ((variable? exp)
         (if (same-variable? exp var) 1 0))
        ((sum? exp)
         (make-sum (deriv (addend exp) var)
                   (deriv (augend exp) var)))
        ((product? exp)
         (make-sum
           (make-product (multiplier exp)
                         (deriv (multiplicand exp) var))
           (make-product (deriv (multiplier exp) var)
                         (multiplicand exp))))
        (else
         (error "unknown expression type -- DERIV" exp))))
(deriv '(+ x 3) 'x)(+ 1 0)  ;(x+3)' =1+0

(deriv '(* x y) 'x)→(+ (* x 0) (* 1 y)) ; (xy)' =0*x+1*y

(deriv '(* (* x y) (+ x 3)) 'x)
(+ (* (* x y) (+ 1 0))
   (* (+ (* x 0) (* 1 y))
      (+  x 3)))

;(xy*(x+3))'=(xy*(1+0)+(0*x+1*y)*(x+3))=xy+y(x+3)

对结果进行简化是一个目标。


参考《编程导论(Java)•5.2》可以用链表保存一元多项式某项的系数和指数,实现一个简单的求导方法。如果需要进行复杂的符号计算,可以参考

简明解释器模式-2

自己写解释器。

package algorithm.deriv;
import static tips.Print.*;//p(x) = System.out.print(x)
/**
求一元多项式的导数。
系数为int便于实现。
 */
public class  Polynomial{//多项式
    private static class Node{
        public int coef;//coefficient 
        public int exp;//指数
        public Node next;
        public Node(int coef,int exp){
            this.coef=coef;
            this.exp=exp;
        }

        public Node setNext(int coef,int exp){
            this.next=new Node(coef,exp);
            return this.next;
        }
    }


    public static Node getDeriv(Node head){
        Node derivHead = null;//导数链表的头结点
        Node p = null;
        int _coef,_exp;//导数结点的域
        while(head!=null){
            if(head.exp!=0){
                _coef = head.exp*head.coef;
                _exp=head.exp-1;
                p =(derivHead==null)? (derivHead=new Node(_coef,_exp)): p.setNext(_coef,_exp);
            }
            head = head.next;
        }
        return derivHead;    
    }

    public static void printList(Node head) {
        while(head!=null){
            p(head.coef);
            if(head.exp!=0){
                String s = (head.exp==1)?"x":"x^"+head.exp;
                p(s);
            }
            if(head.next!=null&&head.next.coef>0)
                p(" + ");//负号自带
            head=head.next;
        }
        pln();
    }

    public static void test() {
        Node head=new Node(6,5);
        Node p=head.setNext(-2,3);
        p=p.setNext(3,2);
        p=p.setNext(-1,0);
        p=null;//已到尾节点
        p("f(x) = ");
        printList(head);
        Node derivHead=getDerivatives(head);
        p("f(x)'= ");
        printList(derivHead);
    }
}

f(x) = 6x^5-2x^3 + 3x^2-1
f(x)'= 30x^4-6x^2 + 6x


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值