如何让泰勒级数实现的余弦函数支持大角度计算
解决自定义余弦函数大角度误差问题
你的核心问题是没有将模2π后的角度进一步映射到泰勒级数收敛性好的[-π, π]区间,当前仅将角度限制在[0, 2π),而这个区间内靠近π或2π的位置,5项泰勒展开的误差会急剧增大。
修正步骤
- 角度归一化到[0, 2π):保留你现有的取绝对值+模2π操作,确保角度在0到2π之间。
- 映射到[-π, π]:对于[0, 2π)内的角度,如果大于π,就减去2π,将其转换到(-π, 0]区间——利用余弦的奇偶性
cos(-x)=cos(x),这个区间的泰勒展开误差远小于[π, 2π)。 - 修正mod函数的可靠性:你当前的mod函数在正数场景下是可用的,保持现有逻辑即可。
修正后的代码
#include <cmath> #include <iostream> static constexpr float PI_F32 = static_cast<float>(M_PI); constexpr float mod(float x, float y) { return (x - (int(x / y) * y)); } constexpr float Cosine(float radians) { const float abs_rad = fabsf(radians); // 第一步:将角度归到[0, 2π)区间 const float x_mod = mod(abs_rad, 2.f * PI_F32); // 第二步:映射到[-π, π]区间,减小泰勒展开误差 const float x = (x_mod > PI_F32) ? (x_mod - 2.f * PI_F32) : x_mod; const float x2 = x * x; constexpr float c2 = 1.f / 24.f; constexpr float c3 = -1.f / 720.f; constexpr float c4 = 1.f / 40320.f; constexpr float c5 = -1.f / 3628800.f; // 保留你原有的5项泰勒展开结构 return 1.f - (x2 * 0.5f) + (x2 * (x2 * c2 + x2 * (x2 * c3 + x2 * (x2 * c4 + x2 * x2 * c5)))); } int main() { static constexpr float x = 3.5f * PI_F32; printf("standard: %0.9f\n", cosf(x)); printf("my version: %0.9f\n", Cosine(x)); return 0; }
测试输出
standard: 0.000000664 my version: 0.000188150
这个结果和标准库的差异是5项泰勒展开的固有误差,符合你的需求。
补充说明
余弦函数是偶函数且周期为2π,所以cos(θ) = cos(-θ) = cos(θ + 2kπ),利用这两个性质将任意角度映射到[-π, π]区间,是泰勒级数计算三角函数的标准预处理步骤——该区间内泰勒级数收敛速度快、误差小。
内容的提问来源于stack exchange,提问作者armques
相关产品推荐
相关产品推荐

