自定义函数调用pow()与main()直接调用结果不同的原因排查
自定义函数调用pow()与直接调用结果不一致的原因
先看这段代码及运行输出:
/***************************************************** * Compile command: * gcc -Wall -o powhat powhat.c -lm *****************************************************/ #include <stdio.h> #include <math.h> float topowerof3(float f) { f = pow(f,3); return f; } int main() { printf("275 to the power of 3:\n"); printf("topowerof3(): %f\n", topowerof3(275)); printf("pow() : %f\n", pow(275,3)); return 0; }
输出结果:
275 to the power of 3: topowerof3(): 20796876.000000 pow() : 20796875.000000
问题核心在于单精度float与双精度double的精度差异,结合pow函数的类型特性导致:
- 标准库
pow()函数的参数和返回值都是double类型,双精度的有效位数足够覆盖275³(20796875是整数,完全在double的精确表示范围内),计算结果准确。 - 在main中直接调用
pow(275,3)时,传入的int类型参数会自动转换为double进行计算,最终得到精确的20796875.0。 - 自定义函数
topowerof3用float接收参数:传入的275先转为float(这一步没问题),但调用pow时,float会被转成double计算,得到准确的20796875.0。但接下来要把这个double值存回float类型的变量f——float的有效位数仅约6-7位,20796875是8位数字,超出了float的精确表示范围,因此会被舍入到最近的可表示float值,也就是20796876.0。最后返回这个已舍入的float值,printf输出时再转成double,但舍入操作已经发生,结果自然和直接调用pow不同。
如果想让自定义函数结果准确,要么把函数的参数、返回值都改为double类型,要么直接用f*f*f的整数/浮点运算来计算三次方,绕开pow的类型转换和精度问题。
内容的提问来源于stack exchange,提问作者Rather Vi
相关产品推荐
相关产品推荐

