记得曾经有人提出过这个问题——如何模拟正弦函数。
我试着编了一个正弦和反正弦的函数。
算法:二分搜索,有些像搜索算法里的二分法,算试一种推广吧,我在单位圆里面对单位圆上的 坐标进行二分搜索,直到找到匹配的坐标为止;
——经过测试,和标准数学函数的正弦函数误差 几乎为0,
由于水平有限,让大家见笑了。
下面贴出代码(有注释,如果不懂,请提出来):
/*正弦和反正弦函数*/ /*为了和标准数学函数区别,正弦函数为sinof()反正弦函数为arcsin()*/ #include <math.h> typedef struct num{double x;double y;}num; num *midof(num *a,num *b) /*求角平分线于单位圆的交点*/ {double x1,y1,z; num *mid=(num*)malloc(sizeof(num)); x1=(a->x+b->x)/2; y1=(a->y+b->y)/2; z=sqrt(100000000/(x1*x1+y1*y1)); mid->x=z*x1; mid->y=z*y1; return mid;}
double doarcsin(double n) /*搜索函数,可以搜索0-1*/ {num *a=(num*)malloc(sizeof(num)); /*a为上界,b为下界,mid为中间坐标*/ num *b=(num*)malloc(sizeof(num)); num *mid=(num*)malloc(sizeof(num)); double f,t,answer,s,i=45; a->x=0;a->y=10000; answer=90; /*尽量让坐标数值大,充分利用double的整数位,保证精确搜索*/ b->x=10000;b->y=0; t=10000*n;f=sqrt(100000000-t*t); mid=midof(a,b); s=(mid->x-f)*(mid->x-f)+(mid->y-t)*(mid->y-t); /*当sin 值达于0.6时以横坐标为判断*/ if(n>=0.6){while(s>=0.0000000001) { if(mid->x>f){b->x=mid->x;b->y=mid->y;i=i/2;} if(mid->x<=f){a->x=mid->x;a->y=mid->y;answer=answer-i;i=i/2;} mid=midof(a,b); s=sqrt((mid->x-f)*(mid->x-f)+(mid->y-t)*(mid->y-t)); } } else {while(s>=0.0000000001) { /*以纵坐标判断*/ if(mid->y<t){b->x=mid->x;b->y=mid->y;i=i/2;} if(mid->y>=t){a->x=mid->x;a->y=mid->y;answer=answer-i;i=i/2;} mid=midof(a,b); s=sqrt((mid->x-f)*(mid->x-f)+(mid->y-t)*(mid->y-t)); }} free(a); free(b); free(mid); return answer; } double arcsin(double n) /*反正弦函数,把所有情况化为0-1的情况然后求解*/ {if(n>1||n<-1){printf("wrong input\n");getch();exit(0);} else if(n>=0)return (doarcsin(n)); else return (-1*doarcsin((-1*n))) ;}
double dosinof(double n) /*正弦搜索函数,计算0-90度的正弦值*/ {num *a=(num*)malloc(sizeof(num)); /*a为上界,b为下界,mid为中间坐标*/ num *b=(num*)malloc(sizeof(num)); num *mid=(num*)malloc(sizeof(num)); double answer,s,now=45000000,i=45000000; /*把角度扩大了1000000倍,充分利用double的整数位置,也是搜索准确的关键所在*/ n=n*1000000;
a->x=0;a->y=10000; answer=90; b->x=10000;b->y=0; mid=midof(a,b); s=abs(i-n); i=(i/2); while(s>=0.0000000001)
{ if(now>n){a->x=mid->x;a->y=mid->y;now=now-i;i=(i/2); } else if(now<=n){b->x=mid->x;b->y=mid->y;now=now+i;i=(i/2);} mid=midof(a,b); s=abs(now-n); } answer=mid->y/10000; free(a); free(b); free(mid); return answer;} double sinof(double n) /*正弦函数,把所有情况化归到0-90度然后解决*/ {while(n>180||n<(-180)) {if(n>180)n=n-360; if(n<(-180))n=n+360; } if(n>90)n=180-n; if(n<(-90))n=n+180; if(n>=0)return dosinof(n); else return (-1*dosinof((-1)*n));}