Почему неправильно работает программа, рекуррентно высчитывающая значение синуса через ряд Тейлора?
Условие задачи:"Необходимо написать программу, в которой вводятся значения n и x и выводится сумма ряда с указанной точностью n, а также сумма ряда с максимально возможной точностью" Например, для значения x = 32.2 не выводится заданная точность, а максимальная печатается. Может быть есть ошибки, которые я не могу увидеть? Объясните, пожалуйста. Заранее благодарен!
#include <stdio.h>
#include <math.h>
#define _CRT_SECURE_NO_WARNINGS
// Определение значения эпсилон
#define LDBL_EPSILON pow(2,-63)
// Функция для вычисления максимально возможной точности через эпсилон
int max_accuracy(long double x, long double n, long double e)
{
int i;
long double memory = x;
for (i = 0; i < n; i++)
{
memory *= -x * x / ((2 * i + 2) * (2 * i + 3));
// Проверяем условие окончания итераций
if (fabsl(memory) <= e)
{
break;
}
}
return i;
}
long double max_sum(long double x, long double n, long double e)
{
int i;
long double sum_i = x;
long double memory = x;
for (i = 0; i < n; i++)
{
memory *= -x * x / ((2 * i + 2) * (2 * i + 3));
sum_i += memory;
// Проверяем условие окончания итераций
if (fabsl(memory) <= e)
{
break;
}
}
return sum_i;
}
int main()
{
long double n, x, sum, term = 0;
printf("input n:");
scanf_s("%Lf", &n);
printf("input x:");
scanf_s("%Lf", &x);
// Определение значения эпсилон
long double e = LDBL_EPSILON;
int maxN = max_accuracy(x, n, e); // Вычисление максимально возможной точности
// Итерации для вычисления синуса с помощью формулы Тейлора
sum = x;
long double member = x;
for (int i = 0; i <= maxN; i++) {
member *= (-x * x / ((2 * i + 2) * (2 * i + 3)));
sum += member;
if (i == n) {
printf("given accuracy: %.15lf\n", sum);
}
}
printf("sin max accuracy: %.15lf\n", max_sum(x,n,e));
printf("sin math.h: %.15lf", sinl(x));
return 0;
}
Ответы (2 шт):
При создании функции int max_accuracy(long double x, long double n, long double e) вы скопировали код из другой long double max_sum(long double x, long double n, long double e) и совершили типичную ошибку бездумного копирования кода.
Цикл должен заканчиваться до условия, приближения к заданной точности, а не количеству слагаемых.
Нужно удалить лишний аргумент n.
int max_accuracy(long double x, /* long double n,*/ long double e)
{
int i;
long double memory = x;
for (i = 0; /*i < n*/ ; i++)
{
memory *= -x * x / ((2 * i + 2) * (2 * i + 3));
// Проверяем условие окончания итераций
if (fabsl(memory) <= e)
{
break;
}
}
return i;
}
И попутно нужно исправить в функциях printf заменой "%lf" на "%Lf"
В справочниках форумы Тейлора представлены в математическом виде, это когда количество цифр после запятой бесконечно. Но в реальности переменные имеют фиксированную точность. Для того чтобы не накапливать ошибку, нужно складывать от меньшего к большему. Буквально сохранять результаты в массив, и только потом вычислять сумму. Кроме того есть минимальный порог для входного параметра, ниже нельзя - получится бесконечность.