Реализация Sin() на основе шаблона на основе ряда Тейлора дает неверные результаты C++

template<unsigned I>
struct factorial{
    enum{

    value = I * factorial<I -1>::value
    };

};
template<>
struct factorial<0>
{
    enum{ value = 1};
};

template<unsigned pow>
inline double power(double const& value){
    return value * power<pow-1>(value);
}
template<>
inline double power<1>(double const& value){
    return value;
}
template<>
inline double power<0>(double const& value){
    return 1;
}

template<unsigned term>
inline double taylor_polynomial(double const& x){
    return power<term>(x) / factorial<term>::value;
}

template <unsigned term>
inline double taylor_sine_term(double const& x) {
    return (power<term>(-1) / factorial<(2*term)+1>::value) * power<(2*term)+1>(x);
}

template<unsigned terms>
inline double taylor_sine(double const& x){
    return taylor_sine_term<terms-1>(x) + taylor_sine_term<terms>(x);
}
template <>
inline double taylor_sine<0>(double const& x) {
    return taylor_sine_term<0>(x);
}

Используя следующий код, я попытался реализовать функцию sin() на основе ряда Тейлора N, но когда я сравниваю результаты функции, результаты неверны, и я не уверен, почему. Выполнение следующего кода:

std::cout<<sin(2 * M_PI * 0.5)<<"   "<<taylor_sine<13>(2 * M_PI * 0.5);

Результаты в 1.22465e-16 -16546.9

Насколько мне известно, я правильно рассчитываю серию, поэтому я не уверен, что происходит не так.


person Alex Zywicki    schedule 09.07.2015    source источник
comment
Это серия Маклорена. Он сосредоточен на нуле, а не на π.   -  person chris    schedule 09.07.2015
comment
Вы сначала попробовали неметапрограммную версию своей реализации, чтобы убедиться, что она дает правильные результаты?   -  person PaulMcKenzie    schedule 09.07.2015
comment
@chris, так что это будет означать диапазон ввода -pi to pi? а не 0 - 2pi?   -  person Alex Zywicki    schedule 09.07.2015
comment
@AlexZywicki, в этом случае радиус сходимости равен ∞, поэтому ряд Маклорена будет сходиться при x = π (и любом другом x), но это не так для каждого степенного ряда.   -  person chris    schedule 09.07.2015


Ответы (1)


Вы вызываете неправильную функцию для рекурсии:

template<unsigned terms>
inline double taylor_sine(double const& x){
    return taylor_sine_term<terms-1>(x) + taylor_sine_term<terms>(x);
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}

Вы добавляете термин n и термин n-1 вместо добавления термина n и серии Тейлора из n-1 терминов.

person Barry    schedule 09.07.2015
comment
template<unsigned terms> inline double taylor_sine(double const& x){ return taylor_sine_term<terms>(x) + taylor_sine<terms-1>(x); } Нравится? - person Alex Zywicki; 09.07.2015