用c语言实现“归一化角度“后的cos(x)与sin(x)
在C语言中,本人发现网上基本上都是教你如何直接使用C语言库函数来调用cos与sin,但由于很多限制,特别硬件编程,必须要自己写cos和sin函数。网上也有几篇自己实现了cos与sin函数的文章,但是都只有单独实现cos和单独实现sin,没有两个函数一起实现的文章,导致算法完全不一样,造成很多麻烦。 我已经写了一篇文章是“用c语言实现cos(x)与sin(x) 函数以及“绝对值函数”和“阶乘函数””
可以到我的主页去查看那篇文章
但是这个文章里面所提供的代码有一个问题就是:
就是如果输入的弧度特别大,可能会出现超出数据类型范围的问题,导致无法得出正确的值,比如我想求63弧度的sin和cos的值,得出来的结果就完全不对:
这个问题的原因是输入的弧度远远大于了整个圆“2*pi≈6.28318530718” 的弧度值,导致在计算过程中的阶乘,指数时,运行结果会远远超出double类型的数据范围,使结果出错。这里的解决方案是利用“归一化角度”,先将输入的较大的弧度值转化成“2*pi”以内的弧度,再进行计算。
这里就来教一下大家如何先“归一化角度”,再进行sin和cos的计算:
这里我的算法是先判断输入的弧度是否在“-2*pi~2*pi”之间,如果超出范围,那么就求出输入的较大弧度值与“2*pi”的模,然后再用if条件句,将其缩小成一个圆对应的弧度范围里的数。为了不受"math.h"的限制,我自己重新手写了一个“fmod()”函数:
归一化角度部分的代码是这样的:
double pi=3.14159265359;
double MyFmod(double _X, double _Y)
{
return _X - (int)(_X / _Y) * _Y;
}
double NormalizeAngle(double angle) {
if(angle>(2.0*pi)||angle<-(2.0*pi)){
double a = MyFmod(angle + pi, 2.0 * pi);
if (a < 0.0)
{
a += (2.0 * pi);
}
return a - 2.0*pi;
}else{
return angle;
}
}
归一化角度以后,将其带入sin和cos函数中的总代码是这样的:
#include <stdio.h>
//sin(-a)=-sin(a)
//cos(-a)=cos(a)
double pi=3.14159265359;
double MyFmod(double _X, double _Y)
{
return _X - (int)(_X / _Y) * _Y;
}
double NormalizeAngle(double angle) {
if(angle>(2.0*pi)||angle<-(2.0*pi)){
double a = MyFmod(angle + pi, 2.0 * pi);
if (a < 0.0)
{
a += (2.0 * pi);
}
return a - 2.0*pi;
}else{
return angle;
}
}
double fabs_self(double x){
if(x>=0){
x=x;
}else{
x=-x;
}
return x;
}
double power_self(double x,int k){
double sum=1;
double i;
while (k != 0)
{
sum*=x;
--k;
}
return sum;
}
double sin(double x)
{
//****************************
int counter=0;
if(x<0){
counter=1;
}else{
counter =0;
}
x=NormalizeAngle(x); //归一化
x=fabs_self(x);
//****************************
int t,q=1;
double term,factorial=1.0,sum2,sxm,sum1=0;
sum2=x;
for(t=2;;t++)
{
factorial=factorial*t;
if(t%2!=0)
{
sum1=sum2;
q=q*(-1);
sxm=fabs_self(power_self(x,t));
term=sxm/factorial;
sum2=q*term+sum2;
}
if(fabs_self(sum2-sum1)<=1e-5)
break;
}
if(counter==1){
sum2=-sum2;
return sum2;
}
else{
return sum2;
}
}
double cos(double x)
{
//********************
x=NormalizeAngle(x);//归一化
x=fabs_self(x);
//********************
int t,q=1;
double term,factorial=1.0,sum2=1,sxm,sum1=0;
for(t=2;;t++)
{
factorial=factorial*t;
if(t%2==0)
{
sum1=sum2;
q=q*(-1);
sxm=fabs_self(power_self(x,t));
term=sxm/factorial;
sum2=q*term+sum2;
}
if(fabs_self(sum2-sum1)<=1e-5)
break;
}
return sum2;
}
int main()
{
printf("sinx=%f",sin(63));
printf("
");
printf("cosx=%f",cos(63));
return 0;
}
运行结果是:
Google 计算器的计算结果是:
可以看出运行结果是非常精确的!
