Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Метод хорд (На основе готового алгоритма) 
V
    Опции темы
Redstuff
Дата 11.3.2007, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Команда REDSTUFF
**


Профиль
Группа: Участник
Сообщений: 497
Регистрация: 27.5.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Вот есть уже готовый алгоритм метода хорд 
Код

//////////////////////////////////////////////////////////////////////////////
//  Solving nonlinear equations (chords method)
//  (c) Johna Smith, 1996
//
//  Method description:
//    given: f(x)=0, [a;b], f(a)*f(b)<0
//    find x0: f(x0)=0
//    We approximate curve by chord between its borders and get
//    point where the chord crosses X axe as a new border of
//    interval with the root. When interval becomes small enough
//    we can take one of its borders as a solution.
//
//////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <math.h>

// this function returns value of f(x)
double f(double x)
{
 // sin 2x - ln x = 0
 return sin(2*x)-log(x);
}

double Solve(double a, double b, double epsilon)
{
 double u,v,x,y;

 u=f(a); v=f(b);
 do
 {
   // x - new border
   x=(a*v-b*u)/(v-u);
   y=f(x);
   // determine whether x is left or right border
   // f(a)*f(b)<0 condition must be true
   if (y*u<0)
   {
     b=x;
     v=y;
   } else
   {
     a=x;
     u=y;
   }
 } while (b-a>epsilon);
 return x;
}

void main(void)
{
 printf("sin 2x - ln x = 0, [a;b]=[1.3;1.5]");
 printf("\nx0=%f",Solve(1.3,1.5,1e-9));
}


При заданной ф-ии pow(x,2)-2 и отрезке [a;b] = [-5,5].
X0=-1.#IND00 - результат...
Что бы это могло значить?
При рассмотрении данной ф-ии, можно понять, что она на данном интервале имеет 2 корня.


--------------------
ГОСТы, СНиПы, ТУ...
<реклама удалена администрацией форума>
PM MAIL WWW ICQ Skype   Вверх
vinter
Дата 11.3.2007, 18:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



в этом случае здесь
Код

 x=(a*v-b*u)/(v-u);

получается деление на ноль, и так у тебя будет при любой четной ф-ией с инверсными, но равными границами интервала. 


--------------------
Мой блог
PM MAIL WWW   Вверх
Redstuff
Дата 11.3.2007, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Команда REDSTUFF
**


Профиль
Группа: Участник
Сообщений: 497
Регистрация: 27.5.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Мдя... делением на ноль у меня обычно подвисало))... А терь вывод непонятностей.. наверно из-за настроек компилятора? Работаю в VS .NET 2005.

Как поступить тогда например для такой ф-ии pow(x.2)-4 [1;3], точность <1, программа виснит, точность =>1. Выводит рез-ат 2.?


Это сообщение отредактировал(а) Redstuff - 11.3.2007, 18:55


--------------------
ГОСТы, СНиПы, ТУ...
<реклама удалена администрацией форума>
PM MAIL WWW ICQ Skype   Вверх
vinter
Дата 11.3.2007, 19:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата(Redstuff @  11.3.2007,  18:55 Найти цитируемый пост)
Мдя... делением на ноль у меня обычно подвисало))


Цитата(Redstuff @  11.3.2007,  18:55 Найти цитируемый пост)
Работаю в VS .NET 2005.

еще один + компилятору, незачем подвисатьsmile

Цитата(Redstuff @  11.3.2007,  18:55 Найти цитируемый пост)
 программа виснит, точность 

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



--------------------
Мой блог
PM MAIL WWW   Вверх
Redstuff
Дата 11.3.2007, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Команда REDSTUFF
**


Профиль
Группа: Участник
Сообщений: 497
Регистрация: 27.5.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Ага, так и есть цикл получается бесконечный... Буду думать как из него выйти)


--------------------
ГОСТы, СНиПы, ТУ...
<реклама удалена администрацией форума>
PM MAIL WWW ICQ Skype   Вверх
O_Nik
Дата 11.3.2007, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 9.3.2007

Репутация: 1
Всего: 1



программа недоработана:
в этом условие проверяется пересекает ли график ось абсцисс, т.е. находится ли корень в текущем диапазоне и в зависимости от этого устанавливаются границы, но если хорда точно попала в корень это не учтено, потому можно доработать:
и добавить проверку на равенство нулю функции в точке X (это для данного случая)
Код

...
   if (fabs(y)<1E-40)
    {
    return x;
    }

if (y*u<0)
   {
     b=x;
     v=y;
   } else
   {
     a=x;
     u=y;
   }
...

вместо 1E-40 можно поставить оч. маленькую величину, желательно меньше точности расчетов компилятора, конечно можно записать и y==0 но это не корректно сравнивать числа с плавающей точкой точными равенствами.

А вообще надо метод разобрать прежде чем программу писать, тем более метод хорд простейший, тут возможен еще обратный ньюанс при попадании на другую границу X, но не в данном случае.

да и еще при возведении в целую степень не надо исползовать готовую функцию pow, т.к. в целую степень можно возвести циклом обыкновенным, написав свою функцию, функция же pow раскладывает в ряд и считает приближенно, что может быть критично  именно в подобных задачах  выч математики.
PM MAIL   Вверх
Redstuff
Дата 11.3.2007, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Команда REDSTUFF
**


Профиль
Группа: Участник
Сообщений: 497
Регистрация: 27.5.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Вроде справился  smile  

Код

#include "stdafx.h"
#include <conio.h>
#include <iostream>
#include <math.h>
#include <windows.h>
#include <string>

using namespace std;

// ConvertCodepage
// Служебная функция, необходимая для вывода текста
// на русском языке в консольном приложении.
// Входные данные:
// Указатель на преобразуемую ANSI-строку
// Выходные данные:
// Строка в OEM-кодировке
string ConvertCodepage(const char *text) {
    char *buffer=new char[strlen(text)+1];
    if (NULL == buffer)
    return "";
    AnsiToOem(text,buffer);
    string result(buffer);
    delete[] buffer;
    return result;
}

double f(double x)
{
 return x*x-2;
}

int _tmain(int argc, _TCHAR* argv[])
{
double a,b;
double eps;
double u,v,x,y;
cout<<ConvertCodepage("Введите a=");
cin>>a;
cout<<ConvertCodepage("Введите b=");
cin>>b;
if(b<a) cout<<ConvertCodepage("b должно быть больше a");
else {
    if(f(b)*f(a)>0) cout<<ConvertCodepage("Значения фунций должны быть разных знаков");
    else {
        cout<<ConvertCodepage("Введите точность eps=");
        cin>>eps;
        if(eps<0 && eps>abs(b-a)) cout<<ConvertCodepage("Точность должна быть положительна и меньше длины интервала");
        else {
            u=f(a); v=f(b);
            do {
                x=(a*v-b*u)/(v-u);
                cout<<x<<endl;
                y=f(x);   
                if (v*u<0) {
                    b=x;
                    v=y;
                } 
                else {
                    a=x;
                    u=y;
                }
            } while (fabs(b-a)>eps);
        }
    }
}
 getch();
}


Если не трудно постестите... Вроде нашел в готовом алгоритме ошибку, поправьте если не прав..
Готовый:
Код

// f(a)*f(b)<0 condition must be true
   if (y*u<0)

Исправление:
Код

// f(a)*f(b)<0 condition must be true
   if (v*u<0)


Добавлено @ 23:17 
O_Nik, пока редактировал свое письмо, ты успел добавить )


--------------------
ГОСТы, СНиПы, ТУ...
<реклама удалена администрацией форума>
PM MAIL WWW ICQ Skype   Вверх
O_Nik
Дата 12.3.2007, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 9.3.2007

Репутация: 1
Всего: 1



Цитата

if(eps<0 && eps>abs(b-a))

abs ведь целое число возвращает b=2.3, a=2.1, abs(b-a)=0;
если a и b будут разницей меньше 1 то условие будет истино при любом положительном eps т.е. надо fabs 

Цитата

if (y*u<0)

было правильно ведь, если разный знак f(x) и f(a), то сдвигаем "b" к "x", т.е. b=x, иниче "a" с двигаем к "x".
PM MAIL   Вверх
Redstuff
Дата 12.3.2007, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Команда REDSTUFF
**


Профиль
Группа: Участник
Сообщений: 497
Регистрация: 27.5.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 1



O_Nik, если оставить if (y*u<0), то зацикливается программа... при x*x-4


--------------------
ГОСТы, СНиПы, ТУ...
<реклама удалена администрацией форума>
PM MAIL WWW ICQ Skype   Вверх
O_Nik
Дата 12.3.2007, 20:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 9.3.2007

Репутация: 1
Всего: 1



Знаю, что зацикливается, 
промежуточные результаты a и b выводи и увидишь, что зацикливается из-за совпадения с границей корня уравнения, что не корректно учтено в условии.
что можно сделать:
протести свой пример при a=0 и b=2, так чтобы одна граница интервала расширилась относительно корня, и убедись, что ты просто подогнал под свои исходные данные задачу.
можно добавить в код условие дополнительное, например такое (это самое простенькое):
Код

 y=f(x);
...

 if (fabs(f(a)-f(x))<eps||fabs(f(b)-f(x))<eps)
    {
//тут можно выводить корень a, если первое условие, b, если второен условие выполняется (т.е. условия поделить можно на 2 :) ), но в данном случае можно оставить и так
    getch();
    return 0;
    }
...

  if (y*u<0)
   {
    b=x;
    v=y;
   }

и все будет ОК

Это сообщение отредактировал(а) O_Nik - 12.3.2007, 21:04
PM MAIL   Вверх
Redstuff
Дата 12.3.2007, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Команда REDSTUFF
**


Профиль
Группа: Участник
Сообщений: 497
Регистрация: 27.5.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 1



O_Nik, спасибо! + однозначно!


--------------------
ГОСТы, СНиПы, ТУ...
<реклама удалена администрацией форума>
PM MAIL WWW ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0822 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.