函数sin()
和cos()
期望弧度。它们通常是“忠实的”,也就是说,它们在数学结果的 1 ULP范围内产生结果,至少对于多达几千个参数。
#include <stdio.h>
#include <math.h>
int main() {
double a, b, c, d;
a = sin(0.0);
b = sin(0.5 * 3.1415926535897932);
c = cos(0.0);
d = cos(0.5 * 3.1415926535897932);
printf("A = %lf\nB = %lf\nC = %lf\nD = %lf\n", a, b, c, d);
return (0);
}
A = 0.000000
B = 1.000000
C = 1.000000
D = 0.000000
编辑添加:
Camilo Martinez 指出,“Unit in the Last Place”是一个特殊的概念。简单来说,有有限数量的double
值,在零附近更密集:
++-+-+-+---+---+-------+---------------+-------------------------------+--
您正在计算的精确三角值几乎总是介于这两个double
s 之间(唯一的例外是sin(0.0) = 0.0
和cos(0.0) = 1.0
):
++-+-+-+---+---+-------+---------------+-------------------------------+--
| ^ |
lower | upper
double | double
|
exact (mathematical) result
大多数库提供的函数在正常情况下会double
立即为您提供精确结果的上方或数学结果的下方。考虑到问题的难度,这非常好。
一些库提供的函数将为您提供最接近精确结果的双精度输入(甚至1E21
)。这是一个惊人的结果。直到最近,这只能以昂贵的计算为代价来获得,但现在,您甚至可以获得几乎与过去不太准确的函数一样快的结果。
最后,有时您甚至没有申请sin()
或申请cos()
您想要的数字,而只是对其最接近的double
近似值。在您的示例中,一旦修复就是这种情况:您想将sin()
andcos()
应用于 π/2,但不能,因为 π/2 不能表示为 a double
。您必须将它们应用到最近的可用double
位置(这是固定程序所做的)。
这种不准确可能会加剧。他们确实给浮点计算带来了坏名声的过程,但实际上,浮点不准确性复合的方式是非常可预测的,并且可以在编写使用浮点的程序时考虑在内。