C#中Single(单精度浮点数)乘法运算结果异常问题咨询
为什么0.9f * 10转int得到8而不是9?
这其实是浮点数精度的经典问题,完全不是什么低级错误——很多开发者刚接触浮点数的时候都会碰到这个困惑!
核心原因:单精度浮点数的精确性限制
Single(也就是C#里的float)是二进制浮点数,它的存储方式决定了很多十进制小数无法被精确表示。比如你写的0.9f,它在内存里实际存储的并不是精确的0.9,而是一个略小于0.9的近似值(大概是0.899999976158142左右)。
当你把这个近似值乘以10之后,得到的结果是略小于9的数(约8.99999976158142)。而C#里把浮点数强制转换为int的时候,会直接截断小数部分(不是四舍五入),所以这个略小于9的数就被截断成了8。
验证这个现象
你可以用下面的代码打印出0.9f的精确值,就能看到真相:
Single singleVal = 0.9f; Console.WriteLine(singleVal.ToString("F15")); // 输出:0.899999976158142 Console.WriteLine((singleVal * 10.0f).ToString("F15")); // 输出:8.999999761581420
解决办法
如果需要避免这种精度问题,可以根据你的场景选择不同方案:
- 需要精确十进制计算:改用
decimal类型,它是专门为十进制小数设计的,能精确表示0.9这类值:decimal decimalVal = 0.9m; int u = (int)(decimalVal * 10.0m); // u = 9 - 只需要四舍五入到整数:使用
Math.Round方法,它会按照四舍五入规则处理:Single singleVal = 0.9f; int u = (int)Math.Round(singleVal * 10.0f); // u = 9 - 抵消精度误差:如果还是想用
float,可以在转换前加一个很小的epsilon(比如1e-6f)来修正近似值:Single singleVal = 0.9f; int u = (int)(singleVal * 10.0f + 1e-6f); // u = 9
内容的提问来源于stack exchange,提问作者Robo Maklen
相关产品推荐
相关产品推荐

