用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 计算器的计算结果是:

可以看出运行结果是非常精确的!

经验分享 程序员 微信小程序 职场和发展