一种使用多项式快速计算 sin
和 cos
近似值的方法
在嵌入式开发、游戏开发或其他需要快速数学计算的领域,sin
和 cos
函数的计算时间可能会影响程序的整体性能。特别是在对时间敏感、精度要求不高的场景中,传统的 sin
和 cos
函数由于依赖复杂的数值方法实现,可能无法满足性能需求。基于此,这里使用基于5次多项式拟合的快速计算 sin
和 cos
近似值方法。
背景
通常情况下,计算正弦和余弦函数时我们会使用 math.h
标准库中的 sin
和 cos
函数。虽然这些函数提供了非常高的精度,但计算代价相对较高。对于一些场景,如实时动画、物理引擎、嵌入式系统等,性能是关键因素,因此我们希望找到更快的近似计算方法。
多项式拟合概述
通过多项式拟合可以对函数进行逼近,以减少复杂运算。这里采用了一个五次多项式:
P
(
x
)
=
w
0
+
w
1
x
+
w
2
x
2
+
w
3
x
3
+
w
4
x
4
+
w
5
x
5
P(x) = w_0 + w_1x + w_2x^2 + w_3x^3 + w_4x^4 + w_5x^5
P(x)=w0+w1x+w2x2+w3x3+w4x4+w5x5
这个多项式被用来近似计算 sin(x)
和 cos(x)
,并在特定区间(0 到
π
2
\frac{\pi}{2}
2π)内有效。
代码分析
以下是多项式拟合的 sin
和 cos
函数实现:
#include <math.h>
#define w0 1.260e-5
#define w1 0.9996
#define w2 0.002307
#define w3 -0.1723
#define w4 0.006044
#define w5 0.005752
// 有效范围 0 - Π/2
double sine(double x) {
return w0 + x * (w1 + x * (w2 + x * (w3 + x * (w4 + x * w5))));
}
double cose(double x) {
x = M_PI_2 - x;
return w0 + x * (w1 + x * (w2 + x * (w3 + x * (w4 + x * w5))));
}
正弦函数拟合 (sine
)
sine
函数使用五次多项式来逼近sin(x)
。- 系数
w0
到w5
是通过对sin(x)
函数拟合获得的。 - 该方法在区间 0 ≤ x ≤ π 2 0 \leq x \leq \frac{\pi}{2} 0≤x≤2π内具有较高的精度。
余弦函数拟合 (cose
)
cose
函数是基于正弦函数的特性 cos ( x ) = sin ( π 2 − x ) \cos(x) = \sin(\frac{\pi}{2} - x) cos(x)=sin(2π−x)来计算的。- 通过将
x
转换为 π 2 − x \frac{\pi}{2} - x 2π−x,再调用与sine
类似的多项式近似进行计算。
精度与性能
在代码的 main
函数中,我们对角度范围
0
∘
0^\circ
0∘到
9
0
∘
90^\circ
90∘(对应弧度
0
0
0到
π
2
\frac{\pi}{2}
2π)进行正弦和余弦函数的测试,并比较标准库中的 sin
和 cos
与我们多项式近似计算的结果。
for(int i = 0; i <= 90 ; i++) {
double rad = M_PI / 180 * i; // 角度转换为弧度
double y = sin(rad);
double ay = sine(rad);
printf("角度 %03d sin = %.6f sine = %.6f 绝对误差 = %.6f\n", i, y, ay, fabs(ay - y));
}
for(int i = 0; i <= 90 ; i++) {
double rad = M_PI / 180 * i; // 角度转换为弧度
double y = cos(rad);
double ay = cose(rad);
printf("角度 %03d cos = %.6f cose = %.6f 绝对误差 = %.6f\n", i, y, ay, fabs(ay - y));
}
运行结果如下,sin
函数和sine
函数计算结果对比:
角度 000 sin = 0.000000 sine = 0.000013 绝对误差 = 0.000013
角度 001 sin = 0.017452 sine = 0.017459 绝对误差 = 0.000006
角度 002 sin = 0.034899 sine = 0.034901 绝对误差 = 0.000001
角度 003 sin = 0.052336 sine = 0.052333 绝对误差 = 0.000003
角度 004 sin = 0.069756 sine = 0.069751 绝对误差 = 0.000006
角度 005 sin = 0.087156 sine = 0.087148 绝对误差 = 0.000008
角度 006 sin = 0.104528 sine = 0.104519 绝对误差 = 0.000010
角度 007 sin = 0.121869 sine = 0.121859 绝对误差 = 0.000011
角度 008 sin = 0.139173 sine = 0.139162 绝对误差 = 0.000011
角度 009 sin = 0.156434 sine = 0.156423 绝对误差 = 0.000012
角度 010 sin = 0.173648 sine = 0.173636 绝对误差 = 0.000012
角度 011 sin = 0.190809 sine = 0.190798 绝对误差 = 0.000011
角度 012 sin = 0.207912 sine = 0.207901 绝对误差 = 0.000011
角度 013 sin = 0.224951 sine = 0.224940 绝对误差 = 0.000011
角度 014 sin = 0.241922 sine = 0.241912 绝对误差 = 0.000010
角度 015 sin = 0.258819 sine = 0.258809 绝对误差 = 0.000010
角度 016 sin = 0.275637 sine = 0.275628 绝对误差 = 0.000009
角度 017 sin = 0.292372 sine = 0.292363 绝对误差 = 0.000009
角度 018 sin = 0.309017 sine = 0.309008 绝对误差 = 0.000009
角度 019 sin = 0.325568 sine = 0.325559 绝对误差 = 0.000009
角度 020 sin = 0.342020 sine = 0.342011 绝对误差 = 0.000009
角度 021 sin = 0.358368 sine = 0.358359 绝对误差 = 0.000009
角度 022 sin = 0.374607 sine = 0.374597 绝对误差 = 0.000010
角度 023 sin = 0.390731 sine = 0.390721 绝对误差 = 0.000010
角度 024 sin = 0.406737 sine = 0.406726 绝对误差 = 0.000011
角度 025 sin = 0.422618 sine = 0.422606 绝对误差 = 0.000012
角度 026 sin = 0.438371 sine = 0.438358 绝对误差 = 0.000013
角度 027 sin = 0.453990 sine = 0.453976 绝对误差 = 0.000014
角度 028 sin = 0.469472 sine = 0.469456 绝对误差 = 0.000015
角度 029 sin = 0.484810 sine = 0.484793 绝对误差 = 0.000017
角度 030 sin = 0.500000 sine = 0.499982 绝对误差 = 0.000018
角度 031 sin = 0.515038 sine = 0.515018 绝对误差 = 0.000020
角度 032 sin = 0.529919 sine = 0.529898 绝对误差 = 0.000021
角度 033 sin = 0.544639 sine = 0.544616 绝对误差 = 0.000023
角度 034 sin = 0.559193 sine = 0.559168 绝对误差 = 0.000025
角度 035 sin = 0.573576 sine = 0.573550 绝对误差 = 0.000027
角度 036 sin = 0.587785 sine = 0.587757 绝对误差 = 0.000028
角度 037 sin = 0.601815 sine = 0.601785 绝对误差 = 0.000030
角度 038 sin = 0.615661 sine = 0.615629 绝对误差 = 0.000032
角度 039 sin = 0.629320 sine = 0.629287 绝对误差 = 0.000034
角度 040 sin = 0.642788 sine = 0.642752 绝对误差 = 0.000035
角度 041 sin = 0.656059 sine = 0.656022 绝对误差 = 0.000037
角度 042 sin = 0.669131 sine = 0.669092 绝对误差 = 0.000039
角度 043 sin = 0.681998 sine = 0.681958 绝对误差 = 0.000040
角度 044 sin = 0.694658 sine = 0.694617 绝对误差 = 0.000042
角度 045 sin = 0.707107 sine = 0.707064 绝对误差 = 0.000043
角度 046 sin = 0.719340 sine = 0.719295 绝对误差 = 0.000044
角度 047 sin = 0.731354 sine = 0.731308 绝对误差 = 0.000046
角度 048 sin = 0.743145 sine = 0.743098 绝对误差 = 0.000047
角度 049 sin = 0.754710 sine = 0.754662 绝对误差 = 0.000048
角度 050 sin = 0.766044 sine = 0.765996 绝对误差 = 0.000049
角度 051 sin = 0.777146 sine = 0.777096 绝对误差 = 0.000050
角度 052 sin = 0.788011 sine = 0.787960 绝对误差 = 0.000051
角度 053 sin = 0.798636 sine = 0.798584 绝对误差 = 0.000052
角度 054 sin = 0.809017 sine = 0.808964 绝对误差 = 0.000053
角度 055 sin = 0.819152 sine = 0.819099 绝对误差 = 0.000053
角度 056 sin = 0.829038 sine = 0.828983 绝对误差 = 0.000054
角度 057 sin = 0.838671 sine = 0.838615 绝对误差 = 0.000055
角度 058 sin = 0.848048 sine = 0.847992 绝对误差 = 0.000056
角度 059 sin = 0.857167 sine = 0.857110 绝对误差 = 0.000057
角度 060 sin = 0.866025 sine = 0.865967 绝对误差 = 0.000058
角度 061 sin = 0.874620 sine = 0.874560 绝对误差 = 0.000059
角度 062 sin = 0.882948 sine = 0.882887 绝对误差 = 0.000060
角度 063 sin = 0.891007 sine = 0.890945 绝对误差 = 0.000062
角度 064 sin = 0.898794 sine = 0.898731 绝对误差 = 0.000063
角度 065 sin = 0.906308 sine = 0.906243 绝对误差 = 0.000065
角度 066 sin = 0.913545 sine = 0.913478 绝对误差 = 0.000067
角度 067 sin = 0.920505 sine = 0.920436 绝对误差 = 0.000069
角度 068 sin = 0.927184 sine = 0.927113 绝对误差 = 0.000071
角度 069 sin = 0.933580 sine = 0.933507 绝对误差 = 0.000074
角度 070 sin = 0.939693 sine = 0.939616 绝对误差 = 0.000076
角度 071 sin = 0.945519 sine = 0.945439 绝对误差 = 0.000079
角度 072 sin = 0.951057 sine = 0.950974 绝对误差 = 0.000082
角度 073 sin = 0.956305 sine = 0.956219 绝对误差 = 0.000086
角度 074 sin = 0.961262 sine = 0.961173 绝对误差 = 0.000089
角度 075 sin = 0.965926 sine = 0.965833 绝对误差 = 0.000093
角度 076 sin = 0.970296 sine = 0.970199 绝对误差 = 0.000096
角度 077 sin = 0.974370 sine = 0.974270 绝对误差 = 0.000100
角度 078 sin = 0.978148 sine = 0.978044 绝对误差 = 0.000104
角度 079 sin = 0.981627 sine = 0.981519 绝对误差 = 0.000108
角度 080 sin = 0.984808 sine = 0.984696 绝对误差 = 0.000112
角度 081 sin = 0.987688 sine = 0.987573 绝对误差 = 0.000115
角度 082 sin = 0.990268 sine = 0.990150 绝对误差 = 0.000118
角度 083 sin = 0.992546 sine = 0.992425 绝对误差 = 0.000121
角度 084 sin = 0.994522 sine = 0.994398 绝对误差 = 0.000124
角度 085 sin = 0.996195 sine = 0.996069 绝对误差 = 0.000126
角度 086 sin = 0.997564 sine = 0.997437 绝对误差 = 0.000127
角度 087 sin = 0.998630 sine = 0.998502 绝对误差 = 0.000128
角度 088 sin = 0.999391 sine = 0.999264 绝对误差 = 0.000127
角度 089 sin = 0.999848 sine = 0.999723 绝对误差 = 0.000125
角度 090 sin = 1.000000 sine = 0.999879 绝对误差 = 0.000121
cos
函数和cose
函数计算结果对比:
角度 000 cos = 1.000000 cose = 0.999879 绝对误差 = 0.000121
角度 001 cos = 0.999848 cose = 0.999723 绝对误差 = 0.000125
角度 002 cos = 0.999391 cose = 0.999264 绝对误差 = 0.000127
角度 003 cos = 0.998630 cose = 0.998502 绝对误差 = 0.000128
角度 004 cos = 0.997564 cose = 0.997437 绝对误差 = 0.000127
角度 005 cos = 0.996195 cose = 0.996069 绝对误差 = 0.000126
角度 006 cos = 0.994522 cose = 0.994398 绝对误差 = 0.000124
角度 007 cos = 0.992546 cose = 0.992425 绝对误差 = 0.000121
角度 008 cos = 0.990268 cose = 0.990150 绝对误差 = 0.000118
角度 009 cos = 0.987688 cose = 0.987573 绝对误差 = 0.000115
角度 010 cos = 0.984808 cose = 0.984696 绝对误差 = 0.000112
角度 011 cos = 0.981627 cose = 0.981519 绝对误差 = 0.000108
角度 012 cos = 0.978148 cose = 0.978044 绝对误差 = 0.000104
角度 013 cos = 0.974370 cose = 0.974270 绝对误差 = 0.000100
角度 014 cos = 0.970296 cose = 0.970199 绝对误差 = 0.000096
角度 015 cos = 0.965926 cose = 0.965833 绝对误差 = 0.000093
角度 016 cos = 0.961262 cose = 0.961173 绝对误差 = 0.000089
角度 017 cos = 0.956305 cose = 0.956219 绝对误差 = 0.000086
角度 018 cos = 0.951057 cose = 0.950974 绝对误差 = 0.000082
角度 019 cos = 0.945519 cose = 0.945439 绝对误差 = 0.000079
角度 020 cos = 0.939693 cose = 0.939616 绝对误差 = 0.000076
角度 021 cos = 0.933580 cose = 0.933507 绝对误差 = 0.000074
角度 022 cos = 0.927184 cose = 0.927113 绝对误差 = 0.000071
角度 023 cos = 0.920505 cose = 0.920436 绝对误差 = 0.000069
角度 024 cos = 0.913545 cose = 0.913478 绝对误差 = 0.000067
角度 025 cos = 0.906308 cose = 0.906243 绝对误差 = 0.000065
角度 026 cos = 0.898794 cose = 0.898731 绝对误差 = 0.000063
角度 027 cos = 0.891007 cose = 0.890945 绝对误差 = 0.000062
角度 028 cos = 0.882948 cose = 0.882887 绝对误差 = 0.000060
角度 029 cos = 0.874620 cose = 0.874560 绝对误差 = 0.000059
角度 030 cos = 0.866025 cose = 0.865967 绝对误差 = 0.000058
角度 031 cos = 0.857167 cose = 0.857110 绝对误差 = 0.000057
角度 032 cos = 0.848048 cose = 0.847992 绝对误差 = 0.000056
角度 033 cos = 0.838671 cose = 0.838615 绝对误差 = 0.000055
角度 034 cos = 0.829038 cose = 0.828983 绝对误差 = 0.000054
角度 035 cos = 0.819152 cose = 0.819099 绝对误差 = 0.000053
角度 036 cos = 0.809017 cose = 0.808964 绝对误差 = 0.000053
角度 037 cos = 0.798636 cose = 0.798584 绝对误差 = 0.000052
角度 038 cos = 0.788011 cose = 0.787960 绝对误差 = 0.000051
角度 039 cos = 0.777146 cose = 0.777096 绝对误差 = 0.000050
角度 040 cos = 0.766044 cose = 0.765996 绝对误差 = 0.000049
角度 041 cos = 0.754710 cose = 0.754662 绝对误差 = 0.000048
角度 042 cos = 0.743145 cose = 0.743098 绝对误差 = 0.000047
角度 043 cos = 0.731354 cose = 0.731308 绝对误差 = 0.000046
角度 044 cos = 0.719340 cose = 0.719295 绝对误差 = 0.000044
角度 045 cos = 0.707107 cose = 0.707064 绝对误差 = 0.000043
角度 046 cos = 0.694658 cose = 0.694617 绝对误差 = 0.000042
角度 047 cos = 0.681998 cose = 0.681958 绝对误差 = 0.000040
角度 048 cos = 0.669131 cose = 0.669092 绝对误差 = 0.000039
角度 049 cos = 0.656059 cose = 0.656022 绝对误差 = 0.000037
角度 050 cos = 0.642788 cose = 0.642752 绝对误差 = 0.000035
角度 051 cos = 0.629320 cose = 0.629287 绝对误差 = 0.000034
角度 052 cos = 0.615661 cose = 0.615629 绝对误差 = 0.000032
角度 053 cos = 0.601815 cose = 0.601785 绝对误差 = 0.000030
角度 054 cos = 0.587785 cose = 0.587757 绝对误差 = 0.000028
角度 055 cos = 0.573576 cose = 0.573550 绝对误差 = 0.000027
角度 056 cos = 0.559193 cose = 0.559168 绝对误差 = 0.000025
角度 057 cos = 0.544639 cose = 0.544616 绝对误差 = 0.000023
角度 058 cos = 0.529919 cose = 0.529898 绝对误差 = 0.000021
角度 059 cos = 0.515038 cose = 0.515018 绝对误差 = 0.000020
角度 060 cos = 0.500000 cose = 0.499982 绝对误差 = 0.000018
角度 061 cos = 0.484810 cose = 0.484793 绝对误差 = 0.000017
角度 062 cos = 0.469472 cose = 0.469456 绝对误差 = 0.000015
角度 063 cos = 0.453990 cose = 0.453976 绝对误差 = 0.000014
角度 064 cos = 0.438371 cose = 0.438358 绝对误差 = 0.000013
角度 065 cos = 0.422618 cose = 0.422606 绝对误差 = 0.000012
角度 066 cos = 0.406737 cose = 0.406726 绝对误差 = 0.000011
角度 067 cos = 0.390731 cose = 0.390721 绝对误差 = 0.000010
角度 068 cos = 0.374607 cose = 0.374597 绝对误差 = 0.000010
角度 069 cos = 0.358368 cose = 0.358359 绝对误差 = 0.000009
角度 070 cos = 0.342020 cose = 0.342011 绝对误差 = 0.000009
角度 071 cos = 0.325568 cose = 0.325559 绝对误差 = 0.000009
角度 072 cos = 0.309017 cose = 0.309008 绝对误差 = 0.000009
角度 073 cos = 0.292372 cose = 0.292363 绝对误差 = 0.000009
角度 074 cos = 0.275637 cose = 0.275628 绝对误差 = 0.000009
角度 075 cos = 0.258819 cose = 0.258809 绝对误差 = 0.000010
角度 076 cos = 0.241922 cose = 0.241912 绝对误差 = 0.000010
角度 077 cos = 0.224951 cose = 0.224940 绝对误差 = 0.000011
角度 078 cos = 0.207912 cose = 0.207901 绝对误差 = 0.000011
角度 079 cos = 0.190809 cose = 0.190798 绝对误差 = 0.000011
角度 080 cos = 0.173648 cose = 0.173636 绝对误差 = 0.000012
角度 081 cos = 0.156434 cose = 0.156423 绝对误差 = 0.000012
角度 082 cos = 0.139173 cose = 0.139162 绝对误差 = 0.000011
角度 083 cos = 0.121869 cose = 0.121859 绝对误差 = 0.000011
角度 084 cos = 0.104528 cose = 0.104519 绝对误差 = 0.000010
角度 085 cos = 0.087156 cose = 0.087148 绝对误差 = 0.000008
角度 086 cos = 0.069756 cose = 0.069751 绝对误差 = 0.000006
角度 087 cos = 0.052336 cose = 0.052333 绝对误差 = 0.000003
角度 088 cos = 0.034899 cose = 0.034901 绝对误差 = 0.000001
角度 089 cos = 0.017452 cose = 0.017459 绝对误差 = 0.000006
角度 090 cos = 0.000000 cose = 0.000013 绝对误差 = 0.000013
在实际运行中,可以看到最大误差大约在0.000128
,对于精度不高的场景下,sine
和 cose
函数提供的结果与标准库函数之间的绝对误差是可以接受的,对于时间要求高而精度要求相对较低的应用非常有用。
在电脑上进行耗时的测试:
fast sin cos 231 microseconds
sin cos 516 microseconds
可以看到耗时减少了55%。但是这个耗时不准确,不同的平台与代码的优化程度不同,耗时也不相同,但是我们可以看出耗时确实大大减少了。
优点与局限
优点:
- 速度快:与标准库函数相比,这种基于多项式的计算方式避免了复杂的数学运算,如级数展开、迭代方法等,因此执行速度快。
- 实现简单:多项式的实现相对简单,不需要依赖复杂的外部库或算法。
局限:
- 有效范围有限:该算法仅在 0 ≤ x ≤ π 2 0 \leq x \leq \frac{\pi}{2} 0≤x≤2π的范围内有效。如果要计算超出该范围的值,必须通过三角函数的周期性和对称性进行转换。
- 精度有限:虽然在实际测试中绝对误差较小,但由于近似计算,在某些对精度要求非常高的应用场景(如高精度物理模拟)中,可能无法满足需求。
应用场景
- 嵌入式系统:对于一些计算资源有限的设备,如单片机,可以减少复杂函数调用的计算量,并且显著提升系统的响应速度。
- 游戏引擎:在游戏开发中,实时计算是非常重要的,特别是对于需要频繁调用正弦余弦函数的物理引擎和动画渲染等部分。
- 音频信号处理:一些数字信号处理算法中涉及大量的三角函数运算,使用这种近似方法可以大大提升计算效率。
结论
通过五次多项式拟合 sin
和 cos
函数,我们可以在一定范围内快速、有效地计算这两个三角函数。尽管这种方法的精度不如标准库函数,但它在速度上的优势使其非常适合那些对计算时间要求高的应用场景。
本文链接:https://blog.csdn.net/u012028275/article/details/142720783