我能得到多于接近除零的分数?

时间:2013-08-14 14:20:03

标签: c++ c

我想避免除以零,所以我有if语句:

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

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

7 个答案:

答案 0 :(得分:9)

只需使用:

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

请注意>>=之间的区别。如果number > 0,则绝对不是0

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

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

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

答案 1 :(得分:6)

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

如果你的目标是避免+/-无穷大,那么if条件中的数字将取决于分子。当分子为1时,您可以使用DBL_MIN中的FLT_MINmath.h

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

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

答案 2 :(得分:3)

您只需查看:

if (number > 0)  

我无法理解为什么你需要下限。

答案 3 :(得分: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;

答案 4 :(得分:3)

你不能正面检查。 DBL_MAX / 0.5实际上是零除;结果是你从任何其他分区获得的相同无穷大(几乎)为零。

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

答案 5 :(得分: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;

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

答案 6 :(得分:0)

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

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

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