我离零的除法有多近
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_MIN
或FLT_MIN
。
如果你的目标是在除法后避免巨大的数字,你可以进行除法,然后在除法后检查fabs(number)
是否大于某个值,然后根据需要采取任何行动。
你的问题没有一个正确的答案。
您可以简单地检查:
if (number > 0)
我不明白你为什么需要这个下限。
对于数字类型T,std::numeric_limits可以为您提供所需的一切。例如,你可以这样做来确保min_invertable以上的任何东西都有有限的倒数:
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;
你不能体面地提前检查。CCD_ 17实际上是被零除;结果是,你从任何其他除以(几乎)零得到的无穷大。
有一个简单的解决方案:只需检查结果。std::isinf(result)
将告诉您结果是否溢出,IEEE754告诉您除法在其他情况下不能产生无穷大。(好吧,除了INF/x。这并不是真正产生无穷大,只是保留它。)
通过上溢或下溢产生无益结果的风险取决于分子和分母。
考虑到这一点的安全检查是:
if (den == 0.0 || log2(num) - log2(den) >= log2(FLT_MAX))
/* expect overflow */ ;
else
return num / den;
但您可能希望从CCD_ 19中减去一小部分,以便为后续的算术运算和四舍五入留出回旋余地。
你可以用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)可能是更好的测试。
- 在除法中不需要四舍五入
- 在TFHE(完全快速同态加密)上执行除法
- 使用 int 表示浮点除法 C++
- 而循环:简单的除法程序输出零,不明白为什么
- 余数除法和不允许除以零 (c++) 时遇到问题
- 如何确定涉及 C++ 中除法的算术表达式的数据类型
- 如何使用除法和for_each?
- C++:奇怪的除法输出
- 分配给浮点数的积分文字除法 - 为什么结果是错误的?
- 除法函数返回错误的值
- 检查向量是否使用除法和阻抗算法进行排序
- 不使用算术运算符的除法
- C++编译器能在编译时计算出文字的除法结果吗
- 浮点 由于除法语句而导致的 c++ 异常
- 特征矩阵向量除法
- 在早期的 C 和 C++ 编译器中,手动位移位与乘法和除法的相关性如何?
- 用除法反转向量的元素
- 按运行时常量值重复整数除法
- 将 int 128 除法提升为浮点数
- 用于 3D 矢量的高效除法运算符