精确为零的float/double相等

Bin*_*ngo 9 c++ floating-point

我有一个使用floatsdoubles执行一些计算的算法.

例:

double a;
double b;
double c;
...
double result = c / (b - a);
if ((result > 0) && (result < small_number))
{
    // result is relevant...
} else {
    // result not required...
}
Run Code Online (Sandbox Code Playgroud)

现在,我担心(b - a)可能是零.如果它接近于零而不是零,则无关紧要,因为result它将超出范围是有用的,并且我已经检测到(当(b - a)接近零时,result将接近+/- inf,这不在范围内0- small_number. ..)

但如果结果(b - a)恰好为零,我预计由于除以零而会发生某种平台依赖.我可以将if声明更改为:

if ((!((b-a) == 0.0)) && ((result = c/(b-a)) > 0) && (result < small_number)) {
Run Code Online (Sandbox Code Playgroud)

但我不知道是否(b-a) == 0.0总能检测到零的平等.我已经看到浮点数中存在多个精确零点的表示形式?如何在不进行epsilon检查的情况下测试它们,我不需要(在我的算法中会忽略一个小的epsilon)?

什么是独立的平台检查方式?

编辑:

不确定这对人们是否足够清楚.基本上我想知道如何找到一个表达式,如:

double result = numerator / denominator;
Run Code Online (Sandbox Code Playgroud)

将导致浮点异常,cpu异常,来自操作系统的信号或其他内容....没有实际执行操作并查看它是否会"抛出"...因为检测到这种性质的"抛出"似乎是复杂的和平台特定的.

是否( (denominator==0.0) || (denominator==-0.0) ) ? "Will 'throw'" : "Won't 'throw'";足够?

wal*_*lyk 9

这取决于如何ba得到了他们的价值.零具有浮点格式的精确表示,但更大的问题是几乎 - 但不是非常零的值.检查总是安全的:

if (abs(b-a) > 0.00000001  && ...
Run Code Online (Sandbox Code Playgroud)

0.00000001是任何有意义的值.

  • 为什么几乎但不是很零的数字究竟是一个问题呢?我的算法已经拒绝了几乎但不是很零的分母的结果...... (5认同)
  • 这个答案帮助我进行了搜索。对 abs 与 fabs 和 gcc 持怀疑态度,abs 适用于所有标量类型(我也在 qreal 和 glFloat 上对其进行了测试。)我自己的两分钱正在使用三元内联测试(只要您是维护者或你评论了很多) `double result = c / ((abs((b - a)) &gt; 0.00000001f) ? (b - a) : 0.00000001f) ;` 然而,这个表达就像罪一样丑陋。 (2认同)

Ton*_*nyK 6

这样做的方法如下:不是检查(result < small_number),而是检查

(abs(c) < abs(b - a) * small_number)
Run Code Online (Sandbox Code Playgroud)

然后你所有的烦恼都消失了!c/(b-a)如果此测试通过,的计算将永远不会溢出。