为什么调换==两侧pow运算结果的两个C++ cout语句输出相反?
问题核心原因
这一现象是浮点数精度误差和C++标准库pow函数的实现、底层硬件浮点运算特性共同导致的,和==运算符本身的交换律逻辑无关。
具体原理
pow是<cmath>中面向浮点数设计的计算函数,返回值为double类型,底层通常通过对数、指数运算实现,而非我们认知中的整数乘法,计算结果很容易出现微小的精度偏差,比如理论值为100的结果,实际计算值可能是99.99999999999999或100.00000000000002。- x86架构下的x87浮点寄存器是80位扩展精度,比内存中存储的64位
double精度更高。==两侧操作数的求值顺序、临时值是存在寄存器还是被截断存入内存,都会影响最终的比较结果:- 第一个比较
pow(10,2) == (pow(8,2)+pow(6,2))执行时,pow(10,2)的结果和pow(8,2)+pow(6,2)的和都保留在80位寄存器中比较,精度足够,结果刚好相等,返回1。 - 第二个比较
(pow(8,2)+pow(6,2)) == pow(10,2)执行时,加法结果被临时截断为64位double存入内存,微小的精度误差被放大,再和pow(10,2)的结果比较时就会判定为不相等,返回0。
- 第一个比较
解决方案
- 永远不要直接用
==比较两个浮点数是否相等,改为判断两者差值的绝对值小于可接受的最小误差阈值即可:
#include <iostream> #include <cmath> using namespace std; int main() { const double eps = 1e-9; cout << (fabs(pow(10,2) - (pow(8,2)+pow(6,2))) < eps) << endl; cout << (fabs((pow(8,2)+pow(6,2)) - pow(10,2)) < eps) << endl; return 0; }
- 如果是整数次幂的计算,直接用整数乘法代替
pow函数,完全避免浮点数误差:
cout << (10*10 == (8*8 + 6*6)) << endl; cout << ((8*8 + 6*6) == 10*10) << endl;
内容的提问来源于stack exchange,提问作者de_coding_life
相关产品推荐
相关产品推荐

