PHP字符串浮点数转整数结果异常 8.54强转得到853而非854
为什么执行
(int) ((float) ( "8.54") * 100);返回结果为853而非预期的854? 核心原因是浮点数二进制存储的精度限制:
- 计算机底层用二进制存储浮点数,绝大多数十进制小数无法被精确表示为二进制浮点数。你把字符串
"8.54"强转为单精度float类型时,实际存储的并不是精确的8.54,而是一个略小于8.54的近似值,实际值约为8.5399999... - 这个近似值乘以100之后,得到的结果也不是精确的854,而是约等于853.99999...
- 把浮点数强转为
int类型时,规则是直接截断小数部分取整数,不会做四舍五入,因此853.99999...截断后就得到了853。
单精度float的有效精度仅为6~7位十进制数,本身精度较低,这类精度丢失问题出现的概率更高。
如何将字符串类型的
"8.54"正确转换为整型的854? 根据场景可以选择以下几种可靠方案,完全避开浮点数截断误差:
- 方案1:用精确运算库处理十进制计算
不要直接用原生浮点数做乘法,使用支持高精度十进制运算的库/函数计算即可,以PHP为例可以用bcmath系列函数:// 精确计算8.54*100,0表示结果不保留小数,最后转int即可 $result = (int)bcmul("8.54", "100", 0); - 方案2:直接处理字符串,完全绕开浮点数运算
如果待转换的字符串是固定小数位的数字格式,可以直接去掉小数点后转整数,从根源避免精度问题:$numStr = "8.54"; // 替换掉字符串里的小数点,直接转int得到854 $result = (int)str_replace('.', '', $numStr); - 方案3:浮点数计算后先四舍五入再转整型
如果一定要用浮点数计算,不要直接强转int,先对结果做四舍五入处理再转换:// round函数会把853.9999...这类近似值四舍五入为854,再转int即可 $result = (int)round((float)"8.54" * 100);
注意:涉及金额、精确计数的场景,不要直接依赖浮点数强转整型的结果,非常容易因精度丢失出现计算错误。
内容的提问来源于stack exchange,提问作者The_JohnDavies
相关产品推荐
相关产品推荐

