平时都是直接调用Math库。今天我们看看这个函数应该怎么实现
主要的思路是泰勒展开sin函数取近似值,但是如果角度过大,逼近的速度就会很慢,即需要很多项才行。每一项都是一次循环,所以这很耗费电脑资源。我们在使用泰勒之前希望能先用三角函数的周期性和诱导公式,把角度减到越小越好。
public static Double sin(double angle){
//减小角度
angle%=(Math.PI*2);
上面这一步把角度限制在了(-2PI, 2PI) 里
boolean isneg=false;
if(angle<0){
angle=-angle;
isneg=!isneg;
}
利用诱导公式sin(-x)=-sin(x),进一步将角度限制在[0,2PI)里
if(angle>Math.PI){
isneg=!isneg;
angle-=Math.PI;
}
利用诱导公式,sin(x+PI)=-sin(x),将角度限制到[0, PI)中
if(angle>Math.PI/2){
angle=Math.PI-angle
}
再次使用诱导公式sin(PI-x)=sin(x),将角度缩小到[0,PI/2)
double result=0;
if(angle>Math.PI/4){
result=cos(Math.PI/2-angle);
}
else{
int coeff;
for(int i=0;i<10;i++){
coeff=2*i+1;
result+=Math.pow(-1,i)*Math.pow(angle,coeff)/factorial(coeff);
}
}
return result;
这里通过sin(PI/2-x)=cos(x),进一步将角度减到[0, PI/4)。如果已经在[0, PI/4)这个区间里,就直接使用泰勒展开。现在角度是一个绝对值小于1的数了,收敛速度会很快。
注意cos(), 这是我通过相同原理自创的cos函数,factorial()函数同理。
for循环里面就是一个泰勒展开,大家可以推推看,或者网上搜一下
最后函数返回result就好了