Тема: Нахождение корней уравнения методом бисекции

Мне надо написать программу на LISP. Тема: Нахождение корней уравнения методом бисекции.
Проблема в том, что LISP я первый раз увидела неделю назад и даже не представляю с чего начать.
Помогите пожалуйста!!!

Re: Нахождение корней уравнения методом бисекции

А я про метод бисекции читаю впервый раз и тоже не представляю с чего начать?

Re: Нахождение корней уравнения методом бисекции

Это метод половинного деления

Re: Нахождение корней уравнения методом бисекции

> \"Нахождение
корней уравнения методом бисекции\&quo …  16:48:12)

Есть несколько вопросов..
1 - Где задают такие задачи?
2 - На каком диалекте лиспа, это необходимо решить?
3 - Нужно решение для конкретной функции или общее, с передачей в программу функции и решаемого интервала?
4 - Как быть со случаем, если функция многократно пересекает ось, т.е. имеет несколько корней на данном диапазоне?

Re: Нахождение корней уравнения методом бисекции

> [Re:] Валентина
Если задана функция, например парабола

(defun f (x)
  (- (* x x) 12.)
) ;_ end of defun

и известны диапазоны, в котроых находятся корни - для данного конкретного примера это [-4, -3] и [3, 4] (это числа при подстановке которых в функцию она (функция) меняет знак) можно так:

(defun test (a b delta)
  (if (not (equal (f (/ (+ a b) 2.)) 0.0 delta))
    (if (minusp (* (f a) (f (/ (+ a b) 2.))))
      (test a (/ (+ a b) 2.) delta)
      (test (/ (+ a b) 2.) b delta)
    ) ;_ end of if
    (/ (+ a b) 2.)
  ) ;_ end of if
) ;_ end of defun
;;;вызов
;;;(test 3. 4. 0.00001) -> 3.4641
;;;(test -4. -3. 0.00001) ->-3.4641

Re: Нахождение корней уравнения методом бисекции

> CB
Хороший примерчик! :)
Выложу еще один - для случаев, когда нет корня, заодно, все в одном флаконе...

(defun test (a b f d)
 (if (= a b)
  nil
  ((lambda (r)
    (if (equal (f r) 0. d)
     r
     (if (minusp (* (f a) (f r)))
      (test a r f d)
      (test r b f d)
     ) ;_  if
    ) ;_  if
   ) ;_  lambda
   (/ (+ a b) 2.)
  )
 ) ;_  if
) ;_  defun
;|
Вызов
(test 2 1.6 (lambda(x)(- (* x x) 12.)) 0.00001)
(test 3. 4. (lambda(x)(- (* x x) 12.)) 0.00001)
(test -3. -4. (lambda(x)(- (* x x) 12.)) 0.00001)
|;

Re: Нахождение корней уравнения методом бисекции

> Евгений Елпанов
1. Такие задачи задают в академии заочникам (при этом даже ни разу не показав как этот самый Lisp выглядит)
2. На Common LISP
3. Вообще в задании написано, что нужно общее решение с передачей в программу функции и решаемого интервала,одного интервала.
Т.е. фактически я первый раз увидела lisp 2 недели назад. Знаю как это математически решается, но на язык перевести навряд ли смогу.
Спасибо за решение, попытаюсь разобраться.
Изучаю рекурсию по вашим урокам, очень интересно, а главное понятно. Спасибо.

Re: Нахождение корней уравнения методом бисекции

> CB
Спасибо за код, именно параболу и пытаюсь сделать для начала.

Re: Нахождение корней уравнения методом бисекции

На Common LISP не получается, выдает ошибки :'(

Re: Нахождение корней уравнения методом бисекции

ты бы ошибки сюда переписала...
у меня нету Common LISP и времени им заниматься.
Возможно, в Common LISP нет функции minusp, тогда моя последняя программа будет выглядеть:

(defun test (a b f d)
 (if (= a b)
  nil
  ((lambda (r)
    (if (equal (f r) 0. d)
     r
     (if (> 0(* (f a) (f r)))
      (test a r f d)
      (test r b f d)
     ) ;_  if
    ) ;_  if
   ) ;_  lambda
   (/ (+ a b) 2.)
  )
 ) ;_  if
) ;_  defun

если не запустится - переписывай ошибки, я не телепат...

Re: Нахождение корней уравнения методом бисекции

Все равно ошибка:
;;; An error occurred in function EQUAL:
;;; Error: Wrong number of arguments

Re: Нахождение корней уравнения методом бисекции

Значит, еще и equal надо заменить на < или >...

Re: Нахождение корней уравнения методом бисекции

Например, так:

(defun test (a b f d)
 (if (= a b)
  nil
  ((lambda (r)
    (if (< (- 0. d)(f r)d)
     r
     (if (> 0(* (f a) (f r)))
      (test a r f d)
      (test r b f d)
     ) ;_  if
    ) ;_  if
   ) ;_  lambda
   (/ (+ a b) 2.)
  )
 ) ;_  if
)

Re: Нахождение корней уравнения методом бисекции

Теперь пишет:
#<Win32:stack-overflow #xDCC5F8>

Re: Нахождение корней уравнения методом бисекции

> [Re:] Валентина
А так:

(defun test (a b f d)
  (if (= a b)
    nil
    ((lambda (r)
       (if (< (abs (f r)) d)
         r
         (if (> 0 (* (f a) (f r)))
           (test a r f d)
           (test r b f d)
         ) ;_  if
       ) ;_  if
     ) ;_  lambda
      (/ (+ a b) 2.)
    )
  ) ;_  if
)

Вроде abs в Common Lisp есть http://store.in.ru/docs/gnu/cl/Numerical_Functions.html

Re: Нахождение корней уравнения методом бисекции

> Евгений Елпанов
Извините, не тот знак поставила.
!!!Работает!!!

Re: Нахождение корней уравнения методом бисекции

> CB
!!!!!!!!И Ваша работает!!!!!
Спасибо!!!!

Re: Нахождение корней уравнения методом бисекции

Оказывается что функция minusp в Common Lisp есть: http://store.in.ru/docs/gnu/cl/Predicat … mbers.html
Так что можно возвратиться к варианту
(if (minusp (* (f a) (f r))) вместо
(if (> 0 (* (f a) (f r)))

Re: Нахождение корней уравнения методом бисекции

Спасибо огромное.
А не могли бы вы описать построчно, что где делается, а то я некоторые вещи понимаю чисто интуитивно. Вроде бы так:

(defun test (a b f d)        ;_объявляем функцию
  (if (= a b)                      ;_если a=b то ложь, нет корней
    nil
    ((lambda (r)                   ;_
       (if (< (abs (f r)) d)       ;_если значение |f(r)|<d
         r                         ;_? (я так понимаю r это середина отрезка?))
         (if (minusp (* (f a) (f r))) ;_если на концах правого отрезка разные знаки
           (test a r f d)          ;_посылаем в функцию правый отрезок
           (test r b f d)          ;_иначе левый отрезок
         ) ;_  if
       ) ;_  if
     ) ;_  lambda
      (/ (+ a b) 2.)               ;_
    )
  ) ;_  if
)

А что делать если будет введен промежуток [-5; 5]? Ведь тогда при делении получится что и правый отрезок подходит и левый, но программа берет только правый.

Re: Нахождение корней уравнения методом бисекции

> CB
Есть ))) она не на него ругалась

Re: Нахождение корней уравнения методом бисекции

> [Re:] Валентина
Это как раз тот случай, о котором говорил Евгений

4 — Как быть со случаем, если функция многократно пересекает ось, т.е. имеет несколько корней на данном диапазоне?

В этом диапазоне 2 корня: -3.4641 и 3.4641. Какой получится зависит от ввода диапазона [-5 5] или [5 -5], причем на самом начальном этапе поиска корня:
Если (test -5. 5. (lambda(x)(- (* x x) 12.)) 0.00001)
то условие (> 0 (* (f -5) (f 0))) T
-> (test -5 0 f d)
А в этом диапазоне [-5 0] - уже один корень (-3.4641), он и будет решением.
Если (test 5. -5. (lambda(x)(- (* x x) 12.)) 0.00001)
то условие (> 0 (* (f -5) (f 0))) T
-> (test 5 0 f d)
В этом диапазоне [0 5] тоже один корень (3.4641) - он и будет решением...

Re: Нахождение корней уравнения методом бисекции

Плохо что нельзя корректировать свои вообщения... Здесь ошибочка
Если (test 5. -5. (lambda(x)(- (* x x) 12.)) 0.00001)
то условие (> 0 (* (f 5) (f 0))) T
-> (test 5 0 f d)

Re: Нахождение корней уравнения методом бисекции

> CB
Дело в том что я заранее не знаю какой диапазон введет пользователь.
Есть мысль: допустим ввели диапазон [-5 5]. Задаем шаг 1 и двигаясь от -5 до 5 проверяем все отрезки: [-5 -4],[-4 -3],...,[4 5] на условие различности знаков функции на концах отрезков и те которые подходят уже посылать в test для дальнейшего уточнения.
Как это реализовать?

Re: Нахождение корней уравнения методом бисекции

И еще как заставить lisp выдать конечное решение? Он выдает 1816187/524288, если решить на калькуляторе,то получается верный результат.

Re: Нахождение корней уравнения методом бисекции

[Re: пишет:

Валентина]как заставить lisp выдать конечное решение? Он выдает 1816187/524288

Вообще не понял что это за числа...

> [Re:] Валентина

(defun bisec (a b f d n)
  (defun test (a b)
    (if (= a b)
      nil
      ((lambda (r)
         (if (< (abs (f r)) d)
           r
           (if (> 0 (* (f a) (f r)))
             (test a r)
             (test r b)
           ) ;_  if
         ) ;_  if
       ) ;_  lambda
        (/ (+ a b) 2.)
      )
    ) ;_  if
  ) ;_  defun
  (if (< a b)
    (if (> 0 (* (f a) (f (+ a n))))
      (cons (test a (+ a n)) (bisec (+ a n) b f d n))
      (bisec (+ a n) b f d n)
    ) ;_ end of if
  ) ;_ end of if
) ;_ end of defun
;|
Примеры:
(bisec 0. 30. (lambda(x)(- (* x x) 12.)) 0.00001 0.5) => (3.4641)
(bisec -30. 0. (lambda(x)(- (* x x) 12.)) 0.00001 0.5) => (-3.4641)
(bisec -30. 30. (lambda(x)(- (* x x) 12.)) 0.00001 0.5) => (-3.4641 3.4641)
(bisec 10. 30. (lambda(x)(- (* x x) 12.)) 0.00001 0.5) => nil
(bisec (- (* 3 pi)) (* 3 pi) (lambda(x) (cos x)) 0.00001 0.1) => (-7.85398 -4.71239 -1.5708 1.5708 4.71238 7.85398)
(bisec (- (* 3 pi)) (* 3 pi) (lambda(x) (sin x)) 0.00001 0.1) => (-6.28318 -3.1416 2.31267e-006 3.14159 6.28318 9.42478)
|;