我为泰勒级数编写了以下函数以计算余弦。
double cosine(int x) {
x %= 360; // make it less than 360
double rad = x * (PI / 180);
double cos = 0;
int n;
for(n = 0; n < TERMS; n++) {
cos += pow(-1, n) * pow(rad, 2 * n) / fact(2 * n);
}
return cos;
}
我的问题是,当我输入90时,我得到的答案是-0.000000。 (为什么我得到-0.000而不是0.000?)
有人可以解释为什么以及如何解决这个问题吗?我认为这是由于double的精度所致。这是main():
int main(void){
int y;
//scanf("%d",&y);
y=90;
printf("sine(%d)= %lf\n",y, sine(y));
printf("cosine(%d)= %lf\n",y, cosine(y));
return 0;
}
完全希望您无法获得带有浮点的anything的余弦的精确零输出,而不管您的计算方法有多好。这是浮点如何工作的基础。
余弦的数学零为pi / 2的奇数倍。由于pi是非理性的,因此无法完全表示为double(或任何浮点形式),并且可表示的最接近的相邻值之间的差至少为pi / 2倍DBL_EPSILON
,大约为3e-16
(或其他浮点类型的相应值)。对于pi / 2的奇数倍,您可能会“很幸运”并发现它确实非常接近两个邻居之一,但是平均而言,您会发现它大约1e-16
。因此,您的输入是1e-16
左右已经错误。
现在,余弦在其零处具有斜率+1或-1,因此输出中的误差将与输入中的误差大致成比例。但是要获得精确的零,您需要的误差应小于可表示的最小非零双精度数,即2e-308
左右。这比输入错误小了近300个数量级。
虽然您在理论上可以“幸运”,并且如果pi / 2确实非常接近最接近的可表示倍数,则有一些倍数,但将其建模为随机数的可能性从天文学角度来看很小。我相信甚至有证据表明,存在[[no double x
,其中cos(x)
的正确舍入值为正好为零。对于单精度(float
),可以通过蛮力很容易地确定;对于double
可能也是可行的,但是需要大量的计算。
printf
为什么打印-0.000000
的原因,仅是%f
的默认值是小数点后6位,这远远不能看到第一个有效数字。使用%e
或%g
,还可以选择使用一个较大的精度修饰符,它将为您显示所获得结果的近似值,该结果实际上仍具有一定的意义,并让您知道结果是否良好。