繁体   English   中英

我能得到多近于零的除法?

[英]How close to division by zero can I get?

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

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

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

只需使用:

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

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

如果数字可以为负数,则还可以使用:

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

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

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

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

如果您的目标是避免分割后出现大量数字,则可以进行分割,然后检查fabs(number)是否大于分割后的特定值,然后采取所需的任何操作。

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

您可以简单地检查:

if (number > 0)  

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

对于数字类型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;

您不能体面地事先检查。 DBL_MAX / 0.5有效地除以零; 结果是从任何其他除数(几乎为零)得到的无穷大。

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

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

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

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

但您可能希望将log2(FLT_MAX)上的量减少一小部分,以留出摆动的余地,以进行后续的算术和四舍五入。

您可以使用frexp进行类似的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;

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM