C 和 C++ 编译器如何实现浮点数的相等性判定?
How do C and C++ compilers implement the decision of equality for float numbers?
例如,
float a = 1.0;
float b = 1.2;
puts(a == b? "equal": "not equal");
编译器是按位还是其他方式处理?
(我知道用“==”来判断浮点数是否相等不是一个好的选择,我只是想知道编译器是如何处理这种情况的。)
我假设你的意思是程序编译后,它如何比较两个浮点数。花车的存放方式非常独特。它按符号、指数和分数存储,如 here 所示。因此,除非绝对相等,程序甚至会将 1 和 1.000000000001 视为不同。要检查它们是否 almost 相等,您可以使用以下命令:
bool AlmostEqualRelativeOrAbsolute(float A, float B,
float maxRelativeError, float maxAbsoluteError)
{
if (fabs(A - B) < maxAbsoluteError)
return true;
float relativeError;
if (fabs(B) > fabs(A))
relativeError = fabs((A - B) / B);
else
relativeError = fabs((A - B) / A);
if (relativeError <= maxRelativeError)
return true;
return false;
}
代码是从here获得的,你可能想在网站上阅读更多内容。
gcc 和 clang 使用 UCOMISS x86/x64 指令。
来源:tried it 与 -O3
并检查了汇编输出。
一般的、完整的答案是浮点数是根据 IEEE 754 规范进行比较的。
具体回答你的问题,大多数情况下两个浮点数是按位比较的,有少数例外情况:
- 正负零被认为是相等的
- NaN 被认为不等于一切,甚至不等于 NaN 本身
- 次正规可能在某些操作模式下比较等于零和其他次正规(例如"flush subnormals to zero")
- 除了这些例外,使用常规的按位比较
例如,
float a = 1.0;
float b = 1.2;
puts(a == b? "equal": "not equal");
编译器是按位还是其他方式处理?
(我知道用“==”来判断浮点数是否相等不是一个好的选择,我只是想知道编译器是如何处理这种情况的。)
我假设你的意思是程序编译后,它如何比较两个浮点数。花车的存放方式非常独特。它按符号、指数和分数存储,如 here 所示。因此,除非绝对相等,程序甚至会将 1 和 1.000000000001 视为不同。要检查它们是否 almost 相等,您可以使用以下命令:
bool AlmostEqualRelativeOrAbsolute(float A, float B,
float maxRelativeError, float maxAbsoluteError)
{
if (fabs(A - B) < maxAbsoluteError)
return true;
float relativeError;
if (fabs(B) > fabs(A))
relativeError = fabs((A - B) / B);
else
relativeError = fabs((A - B) / A);
if (relativeError <= maxRelativeError)
return true;
return false;
}
代码是从here获得的,你可能想在网站上阅读更多内容。
gcc 和 clang 使用 UCOMISS x86/x64 指令。
来源:tried it 与 -O3
并检查了汇编输出。
一般的、完整的答案是浮点数是根据 IEEE 754 规范进行比较的。
具体回答你的问题,大多数情况下两个浮点数是按位比较的,有少数例外情况:
- 正负零被认为是相等的
- NaN 被认为不等于一切,甚至不等于 NaN 本身
- 次正规可能在某些操作模式下比较等于零和其他次正规(例如"flush subnormals to zero")
- 除了这些例外,使用常规的按位比较