0

我想避免除以零,所以我有一个if声明:

float number;
//........
if (number > 0.000000000000001) 
  number = 1/number;

我可以安全地使用多小的值来代替0.000000000000001

4

7 回答 7

9

只需使用:

if(number > 0)
    number = 1/number;

>注意和之间的区别>=。如果number > 0,那肯定不是0

如果数字可以是负数,您也可以使用:

if(number != 0)
    number = 1/number;

请注意,正如其他人在评论中提到的那样,检查numbernot0不会阻止您的结果是Infor -Inf

于 2013-08-14T14:22:34.420 回答
6

条件中的数字if取决于您要对结果执行的操作。在(几乎?)所有 C 实现都使用的 IEEE 754 中,除以 0 是可以的:您得到正无穷大或负无穷大。

如果您的目标是避免 +/- Infinity,则if条件中的数字将取决于分子。当分子为 1 时,您可以使用DBL_MINFLT_MINfrom math.h

如果您的目标是在除法后避免大量数字,您可以进行除法,然后检查除法后是否fabs(number)大于某个值,然后根据需要采取任何措施。

你的问题没有一个正确的答案。

于 2013-08-14T14:33:59.177 回答
3

您可以简单地检查:

if (number > 0)  

我不明白你为什么需要下限。

于 2013-08-14T14:25:01.757 回答
3

对于数字类型 T std::numeric_limits 为您提供所需的任何东西。例如,您可以这样做以确保 min_invertible 以上的任何内容都具有有限倒数:

float max_float = std::numeric_limits<float>::max(); 
float min_float = std::numeric_limits<float>::min(); // or denorm_min()
float min_invertible = (max_float*min_float > 1.0f )? min_float : 1.0f/max_float;
于 2013-08-14T16:22:45.577 回答
3

你不能体面地检查前面。DBL_MAX / 0.5实际上是被零除;结果与您从任何其他除以(几乎)零得到的无穷大相同。

有一个简单的解决方案:只需检查结果。std::isinf(result)会告诉你结果是否溢出,IEEE754 会告诉你除法在其他情况下不能产生无穷大。(嗯,除了 INF/x,。这并不是真正产生无穷大,而只是保留它。)

于 2013-08-15T07:58:57.823 回答
1

通过上溢或下溢产生无用结果的风险取决于分子和分母。

考虑到这一点的安全检查是:

if (den == 0.0 || log2(num) - log2(den) >= log2(FLT_MAX))
    /* expect overflow */ ;
else
    return num / den;

但您可能想减少一点,log2(FLT_MAX)以便为后续的算术和四舍五入留出回旋余地。

您可以使用 执行类似的操作frexp,这也适用于负值:

int max;
int n, d;

frexp(FLT_MAX, &max);

frexp(num, &n);
frexp(den, &d);

if (den == 0.0 || n - d > max)
    /* might overflow */ ;
else
    return num / den;

这避免了计算对数的工作,如果编译器可以找到合适的方法,这可能会更有效,但它并不准确。

于 2013-08-15T09:03:24.563 回答
0

对于 IEEE 32 位浮点数,大于 0 的最小可能值为 2^-149。

如果您使用的是 IEEE 64 位,则可能的最小值为 2^-1074。

也就是说,(x > 0) 可能是更好的测试。

于 2013-08-14T14:28:37.723 回答