neu*_*rte 59 c c++ floating-point divide-by-zero
每个人都知道你不应该直接比较花车,而是使用公差:
float a,b;
float epsilon = 1e-6f;
bool equal = (fabs(a-b) < epsilon);
Run Code Online (Sandbox Code Playgroud)
我想知道在分割中使用它之前是否同样适用于将值比较为零.
float a, b;
if (a != 0.0f) b = 1/a; // oops?
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我还需要与epsilon进行比较吗?
R..*_*R.. 67
浮点除以零不是错误.它会在支持浮点异常的实现上引发一个浮点异常(除非你主动检查它们,这是一个无操作),并且具有明确定义的结果:正或负无穷大(如果分子非零),或者NAN(如果分子为零).
当分母非零但非常接近零(例如,低于正常)时,也可能得到无穷大(和溢出异常),但同样这不是错误.这就是浮点的工作原理.
编辑:请注意,正如Eric在评论中指出的那样,这个答案假定了附件F的要求,附件F是C标准的可选部分,详细说明浮点行为并将其与浮点的IEEE标准对齐.在没有IEEE算法的情况下,C不会将浮点除法定义为零(实际上,所有浮点运算的结果都是实现定义的,可能被定义为完全无意义且仍然符合C标准),因此,你正在处理一个不尊重IEEE浮点数的古怪C实现,你将不得不参考你用来回答这个问题的实现的文档.
Eri*_*hil 24
是的,在某些情况下,除以小数可能会产生与除以零相同的效果,包括陷阱.
某些C实现(以及一些其他计算环境)可以在刷新 - 下溢模式下执行,尤其是在使用高性能选项的情况下.在这种模式下,除以非正规可以得到与除以零相同的结果.当使用向量(SIMD)指令时,刷新下溢模式并不罕见.
非正规数是具有浮点格式中最小指数的数字,它们非常小,以至于有效数的隐含位为0而不是1.对于IEEE 754,单精度,这是非零数字,幅度小于2 -126.对于双精度,它是非零数字,幅度小于2 -1022.
正确处理非正规数字(根据IEEE 754)在某些处理器中需要额外的计算时间.为了在不需要时避免这种延迟,处理器可以具有将非正规操作数转换为零的模式.将数字除以非正规操作数将产生与除以零相同的结果,即使通常的结果是有限的.
如其他答案所述,除以零不是采用C标准附件F的C实现中的错误.并非所有实现都可以.在没有实现浮点陷阱的实现中,您无法确定是否启用了浮点陷阱,特别是除零异常的陷阱,而没有关于您的环境的其他规范.
根据您的具体情况,您可能还必须防止应用程序中的其他代码改变浮点环境.
要回答帖子标题中的问题,除以非常小的数字不会导致除数为零,但可能会导致结果变为无穷大:
double x = 1E-300;
cout << x << endl;
double y = 1E300;
cout << y << endl;
double z = y / x;
cout << z << endl;
cout << (z == std::numeric_limits<double>::infinity()) << endl;
Run Code Online (Sandbox Code Playgroud)
这会产生以下输出:
1e-300
1e+300
inf
1
Run Code Online (Sandbox Code Playgroud)
正好只有0.f的除法会将除数除以零.
但是,除以非常小的数字可能会产生溢出异常 - 结果非常大,以至于它不再能由浮点数表示.分裂将返回无限.
无穷大的浮点表示可用于计算,因此如果您的实现的其余部分可以处理它,则可能不需要检查它.
| 归档时间: |
|
| 查看次数: |
14935 次 |
| 最近记录: |