牛顿';Scheme或Common Lisp中的s平方根法

牛顿';Scheme或Common Lisp中的s平方根法,scheme,lisp,common-lisp,Scheme,Lisp,Common Lisp,我无法找出这个程序中的错误。这是方案版本。我也试过普通的Lisp版本。在这两种情况下,程序一直运行,没有任何结果。请帮忙 (define (sqrt1 x) (define (square x) (* x x)) (define (isGoodEnough g x) (< (abs (- (square g) (square x))) 0.01)) (define (average x y) (/ (+ x y) 2)) (def

我无法找出这个程序中的错误。这是方案版本。我也试过普通的Lisp版本。在这两种情况下,程序一直运行,没有任何结果。请帮忙

(define (sqrt1 x)

  (define (square x)
      (* x x))

  (define (isGoodEnough g x)
      (< (abs (- (square g) (square x))) 0.01))

  (define (average x y)
      (/ (+ x y) 2))

  (define (improvedGuess g x)
      (average g (/ x g)))

  (define (sqrt-iter g x)
      (if (isGoodEnough g x)
          g
          (sqrt-iter (improvedGuess g x) x)))

  (sqrt-iter 1.0 x))
(定义(sqrt1 x)
(定义(平方x)
(*x))
(定义(isgoodough g x)
(<(abs(-(平方g)(平方x)))0.01))
(定义(平均x y)
(/(+xy)2))
(定义(改进g x)
(平均克(/x克)))
(定义(sqrt iter g x)
(如果(足够好,g x)
G
(sqrt iter(改进的g x)x)))
(sqrt iter 1.0 x))

足够好了
有一个bug。您正在对当前猜测值
g
和数字
x
进行平方运算。但是由于
g
应该是
x
的平方根,如果你将两者都平方,它们就永远不会接近。你应该只做猜测

(define (isGoodEnough g x)
  (< (abs (- (square g) x)) 0.01))
(定义(isgoodough g x)
(<(abs(-(平方克)x))0.01)

您应该能够自己找到问题。我来教你怎么做。我将使用LispWorks,但它的工作方式与大多数Lisp实现类似

这是您在Common Lisp中的代码:

(defun square (x)
  (* x x))

(defun isGoodEnough (g x)
  (< (abs (- (square g)
             (square x)))
     0.01))

(defun average (x y)
  (/ (+ x y) 2))

(defun improvedGuess (g x)
  (average g (/ x g)))

(defun sqrt-iter (g x)
  (if (isGoodEnough g x)
      g
    (sqrt-iter (improvedGuess g x) x)))

(defun sqrt1 (x)
  (sqrt-iter 1.0 x))
LispWorks会导致堆栈溢出,但如果它处于无限循环中,我们可以手动中断它:

Stack overflow (stack size 53998).
  1 (continue) Extend stack by 50%.
  2 (abort) Return to level 0.
  3 Return to top loop level 0.

Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
:n
是转到下一堆栈帧的命令

CL-USER 10 : 1 > :n
Interpreted call to AVERAGE

CL-USER 11 : 1 > :n
Interpreted call to IMPROVEDGUESS

CL-USER 12 : 1 > :n
Interpreted call to SQRT-ITER
:v
是查看该堆栈帧的变量值的命令。我们看这一帧和下一帧,看看函数是如何被调用的

CL-USER 13 : 1 > :v
Interpreted call to SQRT-ITER:
  G : 1.4142135                    ; current guess
  X : 2.0

CL-USER 14 : 1 > :n
Interpreted call to SQRT-ITER

CL-USER 15 : 1 > :v
Interpreted call to SQRT-ITER:
  G : 1.4142135                    ; prior guess
  X : 2.0
因此,当前猜测和先前猜测是相等的

看看你的代码:

(defun sqrt-iter (g x)
  (if (isGoodEnough g x)
      g
    (sqrt-iter (improvedGuess g x) x)))
只有当猜测不够准确时,才会发生这种递归调用。 使用当前值进行检查:

CL-USER 16 : 1 > (isgoodenough 1.4142135 2.0)
NIL
但它应该是T,因为猜测实际上已经足够好了。 有一只虫子!!让我们看看代码:

(defun isGoodEnough (g x)
  (< (abs (- (square g)
             (square x)))
     0.01))
核实:

CL-USER 18 : 1 > (isgoodenough 1.4142135 2.0)
T
现在LispWorks很酷,让我们使用
:res
命令重新启动当前调用
(sqrt iter 1.4142135 2.0)

CL-USER 19 : 1 > :res
1.4142135

CL-USER 20 > 
我们得到了一个足够好的结果,然后LispWorks又回到了顶级:
1.4142135

该死的!:(感谢Barmer的快速回复。
CL-USER 17 : 1 > (defun isGoodEnough (g x)
                   (< (abs (- (square g)
                              x))
                      0.01))
ISGOODENOUGH
CL-USER 18 : 1 > (isgoodenough 1.4142135 2.0)
T
CL-USER 19 : 1 > :res
1.4142135

CL-USER 20 >