c - 跳过 IEEE 754 中的 "test for zero"检查

标签 c ieee-754

我在一本关于计算机图形学的流行书中读到过这个,

There are many numeric computations that become much simpler if the programmer takes advantage of the IEEE rules. For example, consider the expression:

a = 1 / (1/b + 1/c)

Such expressions arise with resistors and lenses. If divide-by-zero resulted in a program crash (as was true in many systems before IEEE floating-point), then two if statements would be required to check for small or zero values of b or c. Instead, with IEEE floating-point, if b or c is zero, we will get a zero value for a as desired.

但是 b=+0c=-0 的情况呢?然后是a=1/inf-inf=nan。这本书关于这种优化是错误的,还是我误解了什么?看来我们仍然需要至少检查一次 b 和 c 的标志,而不是根本不检查。

编辑 评论中的一个建议是对 NaN 进行后检查。这是“利用”这些数字类型的惯用方式吗?

bool is_nan(float x) { return x != x; }

float optic_thing(float b, float c) {
  float result = 1.0f / (1.0f/b + 1.0f/c);
  if (is_nan(result)) result = 0;
  return result;
}

最佳答案

But what about the case where b=+0 and c=-0?

通过添加 0.0-0.0 转换为 +0.0 而无需分支。

int main(void) {
  double b = +0.0;
  double c = -0.0;
  printf("%e\n", b);
  printf("%e\n", c);
  printf("%e\n", 1.0/(1.0/b + 1.0/c));
  b += 0.0;
  c += 0.0;
  printf("%e\n", 1.0/(1.0/b + 1.0/c));
  return 0;
}

输出

0.000000e+00
-0.000000e+00
nan
0.000000e+00

[编辑] 另一方面,任何接近 0.0 但不是 0.0 的值都可能是数字伪像而不是准确的电阻值.对于像 b = DBL_TRUE_MIN; 这样的 tiny 值对,上面的代码仍然存在问题。 c = -b; 问题是1.0/tiny --> Infinity and +Infinity + -Infinity --> 。可以求助于使用更宽的 float 进行商计算或缩小操作数。

  b += 0.0;
  c += 0.0;
  printf("%Le\n", 1.0/(1.0L/b + 1.0L/c));

  // Lose some precision, but we are talking about real resistors/lenses here.
  b = (float) b + 0.0f;
  c = (float) c + 0.0f;
  printf("%e\n", 1.0/(1.0/b + 1.0/c));

关于c - 跳过 IEEE 754 中的 "test for zero"检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39259874/

相关文章:

c - 奇怪的错误(程序只有在我打印时才能正常工作)

mysql - 使用 C 在 Eclipse 中退出值 - 它们是什么意思?

matlab - matlab中32位十六进制到32位浮点(IEEE 754)的转换

floating-point - go中的浮点运算

c++ - 函数指针寻址具有多个参数的函数

c - C 中的二维初始化语法

c - 为什么它看起来像数组在 c union 体中反向索引?

c++ - float 和 double 有什么区别?

floating-point - tcl_ precision 的状态如何?

floating-point - 在 double 的 MIN/MAX 范围内是否有 double 不能表示的整数?