float转int计算结果异常原因咨询:为何45.3F*100转int得4529?
这其实是单精度浮点数(float)的精度限制导致的典型问题,咱们来慢慢拆解原因:
float的存储本质:无法精确表示所有十进制小数
float是32位单精度浮点数,它的尾数部分只有23位(加上隐含的1位有效位,总共24位)。很多十进制小数在二进制体系里是无限循环的,float只能用有限的二进制位去近似存储这些数。
比如你定义的float myFloat = 45.3F,它在内存里实际存储的近似值并不是精确的45.3,而是一个略小于45.3的数(比如实际值可能是45.299999237060546875)。强制转换的截断行为放大了误差
当你执行myFloat * 100时,这个近似值乘以100后得到的结果是约4529.9999237...,而(int)强制转换的规则是直接截断小数部分,不是四舍五入,所以最终得到的就是4529,而非预期的4530。为什么23.1F能得到正确结果?
这其实是个巧合:23.1的二进制近似值刚好非常接近真实的23.1,乘以100后的结果几乎就是2310.0,截断小数部分后自然得到正确值,但这种情况不具有普遍性。为什么double能解决问题?
double是64位双精度浮点数,尾数部分有52位(加隐含位共53位),精度比float高得多。它能更精确地近似45.3这样的十进制小数,乘以100后的结果会非常接近4530.0,截断后就得到了正确的整数。
额外建议
如果是处理货币、精确计量这类对数值精度要求极高的场景,建议使用专门的十进制精确类型,比如C#里的decimal、Java里的BigDecimal,从根源上避免浮点数的精度误差问题。
内容的提问来源于stack exchange,提问作者IndustProg

