|
Вопрос # 5 085/ вопрос решён / |
|
Доброго времени суток, уважаемые эксперты!
Требуется написать программу на C++, которая находит корни функции методом половинного деления на промежутке от 0 до 10, с шагом 2 и точностью 10^(-8). Функция: cos(x+5)+3sin(ln(1+x^4)). Выходные данные:
2.27525150
5.12795388
9.93419131
У меня получается
2.27527
5.15805
9.9342
Что-то с точностью не так.
Перед началом вычисления все параметры загружаются из файла. Наработка в приложении
Приложение: Переключить в обычный режим- #include <iostream>
- #include <fstream>
- #include <conio.h>
- #include <math.h>
-
- using namespace std;
-
- double eps;
-
- float CalcFunc(float x)
- {
- return cos(x+5)+3*sin(log(1+pow(x,4)));
- }
-
- void CalcRoot(float xn, float xk, float e)
- {
- float fa, fb, fc;
- float c = 0;
- double d = 1;
- float pn = xn, pk = xk;
- int k = 1;
-
- fa = CalcFunc(pn);
- fb = CalcFunc(pk);
- while (d > e)
- {
-
- if (fa*fb < 0)
- {
- c = (pk+pn) / 2;
- fc = CalcFunc(c);
- if (fa*fc < 0) pk = c; else
- if (fb*fc < 0) pn = c;
- d = (pk-pn)/pow(2, double(k));
- k++;
- } else break;
- }
- cout << c << endl;
- }
-
- int main()
- {
- float xn, xk, h, eps;
-
- ifstream inFile("C:\\in.txt");
- inFile >> xn >> xk >> h >> eps;
-
- for (float f = xn; f <= 10; f += h)
- CalcRoot(f, f+h, eps);
- _getch();
- }
|
Вопрос задал: Евгений Eklmn (статус: Посетитель)
Вопрос отправлен: 13 марта 2011, 20:45
Состояние вопроса: решён, ответов: 2.
|
Ответ #1. Отвечает эксперт: Толяныч
Здравствуйте, Трофимов Евгений!
Для повышения точности рекомендовал бы заменить везде float на double .
|
Ответ отправил: Толяныч (статус: 4-ый класс)
Время отправки: 13 марта 2011, 22:03
Оценка за ответ: 5
Комментарий к оценке: Спасибо! Ваш код помог.
|
Ответ #2. Отвечает эксперт: min@y™
Кроме того (float ---> double), вместо "cout << c << endl;" напиши
printf("%.8f\n", c);
|
Ответ отправил: min@y™ (статус: Доктор наук)
Время отправки: 14 марта 2011, 08:17
|
Мини-форум вопроса
Всего сообщений: 3; последнее сообщение — 14 марта 2011, 23:08; участников в обсуждении: 2.
|
Евгений Eklmn (статус: Посетитель), 13 марта 2011, 22:52 [#1]:
double на точность не повлиял
Генерация случайных чисел - слишком важный вопрос, чтобы оставлять его на волю случая. (Роберт Ковзю, Окриджская лаборатория)
|
|
Толяныч (статус: 4-ый класс), 14 марта 2011, 00:28 [#2]:
Правильно. И не поможет. Я на С++ давно не писа'л, потому сразу не разобрался.
Неправильный сам алгоритм. Суть заключается в следующем :
первый этап - перебор по сетке с постоянным шагом. Предполагается, что сетка достаточно частая , и в один интервал не попадет больше одного корня. Если функция на концах интервала с одним знаком, переходим к следующему, а если разная, то переходим к дихотомическому делению, пока интервал локализации корня не станет меньше заданной точности, а этого как раз у тебя и не было. Условия внутреннего и внешего цикла д.быть поменены местами : если во внешнем цикле ( см.выше ) - то continue, иначе входим во внутренний цикл и по условию (x2-x1)<eps делим интервал пополам.
Поскольку С ( с плюсами и без ) порядком подзабыл, пример даю на Дельфи - разберешься. Программа не оптимизирована по скорости : можно было не вычислять 2 раза функцию на концах интервала, а брать значение с прошлого шага. Проверку совпадения знаков делаю не умножением, а конъюнкцией условий - выглядит более громоздко, но выполняется быстрее.
фрагмент кода
Результат :
2.275221496820
5.127953886986
9.934191298485
|
14 марта 2011, 20:42: Статус вопроса изменён на решённый (изменил автор вопроса — Евгений Eklmn)
|
Толяныч (статус: 4-ый класс), 14 марта 2011, 23:08 [#3]:
Чуть что - заходи.
|
5 апреля 2011, 20:28: Вопрос перемещён из тематического раздела Лабораторный практикум » Разное в раздел Лабораторный практикум » C++ модератором Ерёмин А.А.
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|