Реализовать вычисление числа Эйлера Е в степени X
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.
Задание.
Реализовать вычисление числа Эйлера Е в степени X по формуле:
EX = 1+ ∑ (Xk / k!)^2 (1)
k=1
с максимально возможной точностью для двух вещественных типов: float и double. Число значащих цифр для любого типа данных ограничено, значит, начиная с некоторого k, прибавление очередного члена ряда уже не будет влиять на результат – EX. Если мы найдем такой член ряда, то по его величине мы и сможем судить о погрешности вычисления EX. Нахождение такого члена ряда для каждого из названных вещественных типов данных (float и double) и является задачей. Для того чтобы убедиться в корректности программы, необходимо вывести на монитор для каждого типа данных:
Проверьте корректность работы программы при нулевых, положительных, отрицатель-ных и нецелых значениях X. Вычисление EX для каждого из вещественных типов данных удобно вынести в отдельную функцию. Программу можно оформить в виде консольного приложения.
Для того чтобы с помощью потока cout выводить заданное число значащих цифр выра-жения вещественного типа, можно воспользоваться компонентной функцией precision() класса iostream
Следующим образом:
Для первоначальной проверки корректности вычислений напишите программу, которая будет вычислять EX при заданном n. Посмотрите, будет ли уточняться значение EX с ро-стом n.
При X==1 значение EX должно быть равно приблизительно 2.718281. Можно воспользо-ваться также библиотечной функцией exp(), объявленной в заголовочном файле Math.h, для сравнения результатов своих вычислений с библиотечными.
Если при вычислении какой-либо величины (вещественного типа) происходит выход за границу диапазона для данного типа, то состояние ошибки не возникает, а значение величины при выводе представляется как 1.#INF (сокращение от infinite – бесконечный). Это характерное значение можно (и нужно!) проконтролировать с помощью функции
infinity()
, которая в этом случае возвращает значение true. Например:Для типа double надо использовать функцию таким образом:
Для использования функции infinity() надо подключить заголовочный файл:
Если Вам удастся разработать удачный алгоритм вычисления экспоненты, то Ваши результаты будут практически совпадать (до 15 значащих цифр) с библиотечной функцией. Например, для типа double можно получить такие результаты:
X=709.75
Exp = 1.7398368732641691e+308 eps=7.8270482774736306e+291 n=938
Math::exp = 1.7398368732641605e+308
В формуле фигня ((
См. разложение в ряд: Экспонента
Забавная задачка. С разложением экспоненты в ряд Тейлора действительно наврали ))
Но главная собака зарыта во фразе «Если Вам удастся разработать удачный алгоритм вычисления экспоненты». Потому как при вычислении по формуле «в лоб» очень быстро получаем переполнение, не достигая нужной точности.
Ниже решение этой проблемы. Суть в вычислении очередного члена ряда, используя значение члена, вычисленного на предыдущем шаге:
К тому же работает бысто и эффективно.
Спасибо большущее..
А можете объяснить в двух словах программу?
А проще можно реализовать, для студента 1 курса это безумно замудрено)))
Мария, рад был помочь ))
Особо замудрёного тут ничего нет. Единственно, я использовал механизм шаблонов (template), но это чисто от лени — мне было влом копипастить описание структуры и функции под два типа данных: float и double. И компилятор сделал это за меня )).
Можно убрать template'ы, а Tnum заменить в одной копии на float, а во второй на double. А описание структуры можно даже оставить общим с типом double — она используется только для возврата результата из функции и float-значения приведутся к double автоматически.
Кстати, функция factorial() здесь вообще не нужна. Осталась от экспериментов. Только что обратил внимание ))
По программе:
Функция main(), думаю, вопросов не вызывает ))
Функция ex() реализует вычисление значения экспоненты разложением в ряд Тэйлора (см. ссылку от Алана). Ф-ция возвращает структуру, содержащую значение экспоненты (поле value), последний вычисленный член ряда (eps) и количество вычисленных членов ряда (iteration).
Цикл while реализует накопление суммы ряда.
В переменной res накапливается сумма ряда. Переменная prev содержит значение суммы ряда на предыдущей итерации. Если prev становится равной res, это значит, что прибавление последнего члена ряда не повлияло на сумму — т.е. достигнута максимальная точность вычисления и надо завершить цикл.
Переменная k — номер члена ряда или количество вычисленных членов ряда (или — количество итераций, т.е. сколько раз был выполнен цикл while).
Локальная переменная eps — это последний вычисленный член ряда. Финт с его вычислением я описал в своём первом посте. На каждом проходе цикла вычисленное значение eps прибавляется к сумме в res.
Имеются две проверки на арифметическое переполнение в тех местах, где таковое может произойти.
В операторах return создаётся временный объект (структура) для возврата результата и инициализируется вычисленными значениями. В return в самом конце функции от номера члена ряда (k) необходимо отнять единицу, поскольку прибавление этого члена уже не повлияло на конечный результат.
Вот вроде и всё.
Я не поняла, как можно убрать template, я хоть и второкурсница, но для меня тоже пока что замудрено.. Си начали только в этом году учить..