它在pi/2之前的效果还是很好的,但是超过了pi/2后就开始快速偏离标准sin。它在pi处的值比原来的0多了0.075.用这个方法来模拟波动忽动忽停,看起来很呆板,这个效果当然不是我们想要的。
我们可以继续增加泰勒级数项的个数来减小误差,但是这将导致我们的公式非常的冗长。用4项的泰勒级数展开式需要我们进行7次乘法和3次加法来完成。泰勒级数不能同时满足我对精度和效率的要求。
刚刚近似如果能满足sin(pi)=0就好了。从上图我还可以发现另一件事:这个曲线看起来很象抛物线!所以我们来寻找一个尽可能和sin接近的抛物线(公式)。抛物线的范式方程是:A + B x + C x^2.这个公式可以让们控制三个自由度。显然我们需要其满足sine(0) = 0, sine(pi/2) = 1 and sine(pi) = 0. 这样我们就得到了3个等式。A + B 0 + C 0^2 = 0
A + B pi/2 + C (pi/2)^2 = 1
A + B pi + C pi^2 = 0
显然我们至少需要它在1个完整的周期内都符合我们要求。但是我们可以看出,我们缺少的另一半是原抛物线的一个映射。它的公式是:4/pi x + 4/pi^2 x^2。所以我们可以直接这样写:
Code:
if(x > 0) { y = 4/pi x - 4/pi^2 x^2; } else { y = 4/pi x + 4/pi^2 x^2; }
添加一个条件分支不是一个好的方法。它会让程序渐渐的变慢。但是观察一下我们模拟的和标准的图像是多么的接近啊!观察上面两式子,只是中间的一项正负号不同,我的第一个单纯的想法是可以提取x的正负号来消除分支,即使用:x / abs(x)。除法的代价是非常大的,我们来观察一下现在的公式: 4/pi x - x / abs(x) 4/pi^2 x^2。将除法化简后我们得到:4/pi x - 4/pi^2 x abs(x).所以只需要多一步运算我们就得到了我们需要的sin逼近值!下图是结果
它在pi/2之前的效果还是很好的,但是超过了pi/2后就开始快速偏离标准sin。它在pi处的值比原来的0多了0.075.用这个方法来模拟波动忽动忽停,看起来很呆板,这个效果当然不是我们想要的。
我们可以继续增加泰勒级数项的个数来减小误差,但是这将导致我们的公式非常的冗长。用4项的泰勒级数展开式需要我们进行7次乘法和3次加法来完成。泰勒级数不能同时满足我对精度和效率的要求。
刚刚近似如果能满足sin(pi)=0就好了。从上图我还可以发现另一件事:这个曲线看起来很象抛物线!所以我们来寻找一个尽可能和sin接近的抛物线(公式)。抛物线的范式方程是:A + B x + C x^2.这个公式可以让们控制三个自由度。显然我们需要其满足sine(0) = 0, sine(pi/2) = 1 and sine(pi) = 0. 这样我们就得到了3个等式。A + B 0 + C 0^2 = 0
A + B pi/2 + C (pi/2)^2 = 1
A + B pi + C pi^2 = 0
显然我们至少需要它在1个完整的周期内都符合我们要求。但是我们可以看出,我们缺少的另一半是原抛物线的一个映射。它的公式是:4/pi x + 4/pi^2 x^2。所以我们可以直接这样写:
Code:
if(x > 0) { y = 4/pi x - 4/pi^2 x^2; } else { y = 4/pi x + 4/pi^2 x^2; }
添加一个条件分支不是一个好的方法。它会让程序渐渐的变慢。但是观察一下我们模拟的和标准的图像是多么的接近啊!观察上面两式子,只是中间的一项正负号不同,我的第一个单纯的想法是可以提取x的正负号来消除分支,即使用:x / abs(x)。除法的代价是非常大的,我们来观察一下现在的公式: 4/pi x - x / abs(x) 4/pi^2 x^2。将除法化简后我们得到:4/pi x - 4/pi^2 x abs(x).所以只需要多一步运算我们就得到了我们需要的sin逼近值!下图是结果