为何C语言pow传变量和字面量强转int会得到不同结果?
C语言pow函数整数入参结果差异原因
复现代码如下:
int n = 10; printf("%d\n", (int) pow(n, 2)); // 输出99 printf("%d\n", (int) pow(10, 2)); // 输出100
这个现象和int到double的隐式转换没有关系:int取值范围内的所有整数转double都是完全精确的,变量n=10传入pow时确实会被转换为精确的10.0,结果差异来自两方面:
- 对于
pow(10, 2)的调用,两个入参都是编译期可确定的常量,主流编译器(GCC、Clang、MSVC等)不会生成运行时调用数学库pow的指令,而是在编译阶段直接通过常量折叠算出精确结果100.0,后续强转int自然得到100,整个过程没有运行时浮点运算的精度损失。 - 对于
pow(n, 2)的调用,第一个入参是运行时才能确定值的变量,编译器无法提前计算结果,必须生成运行时调用标准数学库pow的指令。pow是为任意浮点数次幂计算设计的通用函数,主流实现采用exp(y * log(x))的近似算法,计算结果存在微小误差:计算10的平方时,实际返回值通常是99.99999999999999这类略小于100的浮点数。
浮点数强转为int类型时,会直接截断小数部分向零取整,不会执行四舍五入,因此略小于100的浮点值强转后就会得到99,和编译期常量折叠得到的精确值转换结果出现明显差异。
开发提示:不要用pow函数计算整数次幂,既容易出现这类精度误差,性能也远低于直接写整数乘法。如果场景特殊必须用pow计算后转整数,可以在转换前加一个极小的偏移值抵消截断误差,示例写法:
(int)(pow(n, 2) + 1e-6)。
内容的提问来源于stack exchange,提问作者Peatherfed
相关产品推荐
相关产品推荐

