Решение упражнения 1.8 из SICP

15 August, 2007 (23:40) | Решения упражнений

Это упражнение не слишком сложное, поэтому на его решении можно заодно продемонстрировать и внутренние определения процедур.

Вот полное решение:

(define (qbrt-iter guess x) 
  (if (good-enough? guess x) 
      guess 
      (qbrt-iter (improve guess x) 
                 x)))
(define (good-enough? guess x) 
  (< (abs (- (qube guess) x)) 0.001))
(define (qube x) (* x x x))
(define (improve guess x) 
  (/ (+ (/ x (square guess)) 
        (* 2 guess)) 
     3))
(define (square x) (* x x))
(define (qbrt x) 
  (qbrt-iter 1.0 x))

А теперь введем блочную структуру и спрячем функции, которые не интересуют пользователя функции qbrt:

(define (qbrt x) 
  (define (qube x) (* x x x)) 
  (define (square x) (* x x)) 
  (define (qbrt-iter guess) 
    (define (good-enough?) 
      (< (abs (- (qube guess) x)) 0.001)) 
    (define (improve) 
      (/ (+ (/ x (square guess)) 
            (* 2 guess)) 
         3)) 
    (if (good-enough?) 
        guess 
        (qbrt-iter (improve)))) 
  (qbrt-iter 1.0))

Все предельно просто.

Comments

Comment from Sergey Khenkin
Date: August 15, 2007, 5:43 pm

Конечно же, можно и здесь применить улучшение алгоритма из упражнения 1.7.
Это остается на откуп любознательному читателю.

Comment from Elvis
Date: August 12, 2012, 3:11 pm

С учетом прошлого задания:


(define (sq3 old-y y x)
(if(good? old-y y)
y
(sq3 y (/ (+(/ x (* y y)) (* 2 y)) 3) x)))


(define (good? old-y y)
(< (abs (- old-y y)) 0.0000000001))


> (sq3 18 1.0 18)
2.620741394208897
> (sq3 27 1.0 27)
3.0

В место первого old-y я пишу значение вычисляемого числа, так как первый раз написать что-то нужно, и это “что-то” не должно совпадать с первым приближением.

Comment from filimon
Date: September 3, 2012, 9:30 pm

Не хотелось ничего усложнять, да и вообще не виделось смысла в каких-то реальных изменениях предыдущей программы (конечно же, кроме процедуры improve). В результате вместе с ненужной теперь average я удалил ещё и square и не стал писать cube (такую маленькую программу они просто делают чуть больше, реальной пользы от них тут нет).

(define (improve guess x)
(/ (+ (* 2 guess)
(/ x (* guess guess)))
3))
(define (good-enough? guess x)
(< (abs (- (improve guess x) guess)) 0.000000000001))
(define (qbrt-iter guess x)
(if (good-enough? guess x)
guess
(qbrt-iter (improve guess x)
x)))
(define (my-qbrt x)
(qbrt-iter 1.0 x))

Comment from les
Date: July 10, 2013, 7:06 pm

у меня этот код работает совсем не правильно

> (qbrt 9)
2.0801035255095734
> (qbrt 16)
2.5198465761144244
>

Comment from ghost
Date: September 1, 2013, 10:13 am

А можно и так :
вместо процедуры improve (guess x ) из проц. sqrt
написать
(define (improve guess x)
(/ (+ (/ x (square guess)) (* 2 guess)) 3))

Comment from Саша
Date: February 9, 2014, 3:24 pm


(define (abss x)
(if (>= x 0)
x
(- x)))

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

(define (y3 y)
(* y y y))

(define (iter y x)
(if (good y x)
y
(iter (improve y x) x)))

(define (improve y x)
(/ (+ (/ x (square y)) (* 2 y)) 3))

(define (good y x)
(< (abss (- x (y3 y))) 0.0001))

(define (x3 x)
(iter 1.0 x))

С моим кодом вычисления происходят очень медленно.

Comment from acrilis
Date: October 10, 2015, 7:57 pm

(define (qbrt x)
  (define (qube x)  (* x x x))
  (define (square x) (* x x))
  (define (qbrt-iter  guess)
    (define (good-enough?)
      (< (abs (- (abs (qube guess)) (abs x))) 0.000000000000000001))
    (define (improve)
      (/ (+ (/ (abs x) (square guess))
            (* 2 (abs guess)))
         3))
    (if (good-enough?)
        guess
        (qbrt-iter (improve))))
    (if (< x 0) (- (qbrt-iter 1.0)) (qbrt-iter 1.0)))

для отрицательных чисел

Write a comment