Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 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
Что-то с точностью не так.
Перед началом вычисления все параметры загружаются из файла. Наработка в приложении

Приложение:
  1. #include <iostream>
  2. #include <fstream>
  3. #include <conio.h>
  4. #include <math.h>
  5.  
  6. using namespace std;
  7.  
  8. double eps;
  9.  
  10. float CalcFunc(float x)
  11. {
  12. return cos(x+5)+3*sin(log(1+pow(x,4)));
  13. }
  14.  
  15. void CalcRoot(float xn, float xk, float e)
  16. {
  17. float fa, fb, fc;
  18. float c = 0;
  19. double d = 1;
  20. float pn = xn, pk = xk;
  21. int k = 1;
  22.  
  23. fa = CalcFunc(pn);
  24. fb = CalcFunc(pk);
  25. while (d > e)
  26. {
  27.  
  28. if (fa*fb < 0)
  29. {
  30. c = (pk+pn) / 2;
  31. fc = CalcFunc(c);
  32. if (fa*fc < 0) pk = c; else
  33. if (fb*fc < 0) pn = c;
  34. d = (pk-pn)/pow(2, double(k));
  35. k++;
  36. } else break;
  37. }
  38. cout << c << endl;
  39. }
  40.  
  41. int main()
  42. {
  43. float xn, xk, h, eps;
  44.  
  45. ifstream inFile("C:\\in.txt");
  46. inFile >> xn >> xk >> h >> eps;
  47.  
  48. for (float f = xn; f <= 10; f += h)
  49. CalcRoot(f, f+h, eps);
  50. _getch();
  51. }


Евгений Eklmn Вопрос решён, но можно продолжить его обсуждение в мини-форуме

Вопрос задал: Евгений 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

Евгений 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++ модератором Ерёмин А.А.

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 16 ноября 2024, 16:38
Выполнено за 0.02 сек.