鉴于PI / 2永远不能在浮点中精确表示,是否可以安全地假设cos(a)永远不能返回精确的零?
如果是这种情况,那么以下伪代码将永远不会进入该块(并且可以安全地删除):
...
y = h/cos(a);
if (!isfinite(a))
{
// handle infinite y
}
答案 0 :(得分:7)
除了零之外,最接近π/ 2的精确倍数的双精度值是6381956970095103 * 2 ^ 797,它等于:
(an odd integer) * π/2 + 2.983942503748063...e−19
因此,对于所有双精度值x,我们有边界:
|cos(x)| >= cos(2.983942503748063...e−19)
请注意,这是数学上精确值的界限,而不是库函数cos
返回的值。在具有高质量数学库的平台上,这个界限非常好,我们可以说cos(x)
对于任何双精度x
都不为零。事实上,事实证明,这不是双重的独特之处;如果cos
被忠实地舍入,则此属性适用于所有IEEE-754基本类型。
但是,这并不是说在一个三角参数减少实施效果极差的平台上永远不会发生这种情况。
更重要的是,值得注意的是,在您的示例中y
可以是无限,而 cos(a)
为零:
#include <math.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
double a = 0x1.6ac5b262ca1ffp+849;
double h = 0x1.0p1022;
printf("cos(a) = %g\n", cos(a));
printf("h/cos(a) = %g\n", h/cos(a));
return 0;
}
编译并运行:
scanon$ clang example.c && ./a.out
cos(a) = -4.68717e-19
h/cos(a) = -inf
答案 1 :(得分:4)
零是可以准确表示的几个值之一。许多系统都有一个查找表来查找sin和cos的常见值,因此可以返回零值并不可想象。
但是在执行除法之前使用delta比较更安全:
if (Abs(cos(a)) < 0.0000001)
{
}
答案 2 :(得分:0)
不,这不能保证,因为cos
本身是用错误计算的,所以它的值很容易就是零。