为何C语言中4.7存储为4.6999999?浮点运算异常原因
为什么部分浮点值在C语言中运算会出现精度异常?
这其实是浮点数在计算机中存储的固有精度问题导致的,咱们一步步拆解来看:
首先看你运行的代码:
#include <stdio.h> #include <math.h> int main(){ int i; float num = 4.700; for(i=1;i<5;i++){ printf("%0.3f\tx%d\t\t=%d\n",num,(int)pow(10,i),(int)(num*pow(10,i))); } return 0; }
对应的控制台输出:
4.7000 x10 =46
4.7000 x100 =469
4.7000 x1000 =4699
4.7000 x10000 =46999
问题根源:二进制浮点数的精度局限
你要明白,float类型是基于二进制的浮点数,它没办法精确表示所有十进制小数。比如4.7这个数,在二进制里是一个无限循环的小数,就像十进制里1/3是0.333...无限循环一样。当你把4.7赋值给float变量时,计算机只能存储它的近似值——这个值其实是略小于4.7的(大概是4.699999809...)。
当你用这个近似值去乘以10的整数倍时,结果会是略小于预期整数的数值:
- 4.699999809 * 10 ≈ 46.99999809,强制转
int时会直接截断小数部分,得到46而非47 - 乘以100后≈469.9999809,转
int后就是469,以此类推
而像1.2这类十进制小数,刚好能被二进制浮点数精确表示(或者说它的近似值和真实值的差距极小,乘以10的整数倍后结果无限接近整数,截断后不会出错),所以运算结果符合你的预期。
解决思路
如果需要得到正确的整数结果,给你两个实用方案:
- 方案一:强制转换前加上0.5做四舍五入,比如把
(int)(num*pow(10,i))改成(int)(num*pow(10,i) + 0.5),这样就能得到你预期的整数 - 方案二:如果是精度要求高的场景(比如货币计算),建议用整数类型存储(比如把4.7元存成47分),从根源上避免浮点数精度问题
内容的提问来源于stack exchange,提问作者Devan
相关产品推荐
相关产品推荐

