C++ 接近零的浮点值是否会导致被零除的错误?

C++ 接近零的浮点值是否会导致被零除的错误?,c++,c,floating-point,divide-by-zero,C++,C,Floating Point,Divide By Zero,每个人都知道不应该直接比较浮动,而是使用公差: float a,b; float epsilon = 1e-6f; bool equal = (fabs(a-b) < epsilon); 在这种情况下,我是否也需要与epsilon进行比较 在这种情况下,我是否也需要与epsilon进行比较 您永远不会收到被零除的错误,因为0.0f在一个 也就是说,您可能仍然希望使用一些公差-尽管这完全取决于您的应用程序。如果“零”值是其他数学运算的结果,则可能得到一个非常小的非零数字,这可能会在除法后导

每个人都知道不应该直接比较浮动,而是使用公差:

float a,b;
float epsilon = 1e-6f;
bool equal = (fabs(a-b) < epsilon);
在这种情况下,我是否也需要与epsilon进行比较

在这种情况下,我是否也需要与epsilon进行比较

您永远不会收到被零除的错误,因为
0.0f
在一个

也就是说,您可能仍然希望使用一些公差-尽管这完全取决于您的应用程序。如果“零”值是其他数学运算的结果,则可能得到一个非常小的非零数字,这可能会在除法后导致意外结果。如果您想将“接近零”的数字视为零,则公差是合适的。然而,这完全取决于您的应用程序和目标

如果您的编译器正在使用,那么除零,以及除一个小到足以导致溢出的值,都将导致+/-无穷大的值。这可能意味着您可能希望包含对非常小的数字的检查(这将导致平台溢出)。例如,在上,
float
double
都符合规范,这可能会导致非常小的除数产生+/-无穷大,就像零值一样


如果您的编译器/平台没有遵循IEEE 754浮点标准,那么我相信结果是特定于平台的

浮点除零不是错误。它在支持浮点异常的实现上引发一个浮点异常(除非您正在积极检查它们,否则它是一个no op),并具有定义良好的结果:正无穷大或负无穷大(如果分子为非零),或者NAN(如果分子为零)

当分母为非零但非常接近零(例如低于正常值)时,也可能得到无穷大(以及溢出异常),但这同样不是错误。这就是浮点运算的原理


编辑:请注意,正如Eric在评论中指出的那样,该回答假设了附录F的要求,附录F是C标准的可选部分,详细说明了浮点行为,并将其与IEEE浮点标准对齐。在没有IEEE算术的情况下,C不定义浮点除以零(事实上,所有浮点运算的结果都是实现定义的,可能被定义为完全无意义的,并且仍然符合C标准),因此如果您处理的是不符合IEEE浮点的古怪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;

只有精确除以0.f才会引发零除异常

但是,除以一个非常小的数字可能会产生溢出异常-结果太大,无法再用浮点表示。除法将返回无穷大


可以在计算中使用无穷大的浮点表示法,因此如果您的其他实现可以处理它,则可能不需要检查它。

是的,在某些情况下,除以小数字可能会产生与除以零相同的效果,包括陷阱

一些C实现(和一些其他计算环境)可能以刷新下溢模式执行,特别是在使用高性能选项的情况下。在此模式下,被低于正常值的数值除会导致与被零除相同的结果。使用矢量(SIMD)指令时,冲洗下溢模式并不少见

低于正常值的数字是那些浮点格式的最小指数非常小,以至于有效位的隐式位是0而不是1。对于IEEE 754,单精度,这是数量级小于2-126的非零数字。对于双精度,它是数量级小于2-1022的非零数字

正确处理低于正常值的数字(根据IEEE 754)在某些处理器中需要额外的计算时间。为了在不需要时避免这种延迟,处理器可能具有将次正常操作数转换为零的模式。然后,将一个数字除以一个低于正常值的操作数将产生与除以零相同的结果,即使通常的结果是有限的

如其他答案所述,在采用C标准附录F的C实现中,除零不是错误。并非所有的实现都这样做。在不启用浮点陷阱的实现中,如果没有关于环境的其他规范,则无法确定是否启用了浮点陷阱,特别是除法为零的异常的陷阱


根据您的情况,您可能还必须防止应用程序中的其他代码改变浮点环境。

根本不检查0。让它猛烈地撞击!每个人都知道,不应该使用容差来比较浮动,而是应该以一种对您想要的内容有意义的方式进行比较@LuchianGrigore它不会崩溃。如果b不完全为0,则不会出现错误。但是如果b太小,结果可能没有意义,这取决于您的应用程序逻辑。@LuchianGrigore,只有当您不知道在0的情况下该怎么办时。但我非常确定,在某些情况下,特别对待0是有意义的。而且,并不是所有的环境都会崩溃,有些只是给了你一个奇怪的值(我不确定它是Na,一个无穷大,或者别的什么东西)。如果它适合你的情况,可能会考虑使用,这真的是个问题吗?很好,0被精确表示,但这是否意味着没有其他值可以与被零除数具有相同的结果?@delnan不太清楚-给出一个问题“接近零的浮点值是否会导致被零除数错误?”-是的,我认为这是一个错误
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;
1e-300
1e+300
inf
1