long double与double有损转换疑问:为何8.1转换后判等为假?
为什么8.1在long double与double转换后比较返回false?
首先要明确:8.1无法用二进制浮点数精确表示,不管是double还是long double类型。十进制的0.1转换成二进制是无限循环的小数(类似十进制里的1/3),所以8.1作为整数部分加这个无限循环小数,只能被浮点数近似存储。
接下来看精度差异导致的问题:
- 在x86平台的GCC和Clang中,
long double通常采用80位扩展精度格式(尾数部分64位),而double是64位格式(尾数部分52位)。前者能提供更高的精度,对8.1的近似程度更接近真实值。 - 当把
long double类型的8.1L转换为double时,因为double的尾数位数更少,会进行舍入操作,得到double能表示的最接近8.1的近似值val2。 - 再将
val2转回long double得到val3,此时val3是基于double的近似值扩展而来,和最初long double的8.1L的近似值存在微小差异,因此val == val3会返回false。
你可以通过打印高精度的数值来直观看到差异:
#include <iostream> #include <iomanip> int main() { const long double val = 8.1L; const double val2 = static_cast<double>(val); const long double val3 = static_cast<long double>(val2); std::cout << std::boolalpha << (val == val3) << '\n'; // 打印高精度数值 std::cout << std::setprecision(20); std::cout << "val: " << val << '\n'; std::cout << "val2: " << val2 << '\n'; std::cout << "val3: " << val3 << '\n'; return 0; }
运行后会看到val和val3的数值存在细微差别,这就是比较不相等的直接原因。
总结:浮点数的本质是近似存储,不同精度类型之间的转换会引入舍入误差,直接用==比较浮点数是否相等是不可靠的,通常应该通过判断两个值的差值是否小于某个极小的误差阈值(比如1e-10)来判断是否“近似相等”。
内容的提问来源于stack exchange,提问作者Martin Fehrs
相关产品推荐
相关产品推荐

