1. 问题描述
关于数字精度问题,很多同学都肯定不陌生了,最经典的就是JS中的0.1+0.2

2. 具体表现
C#中也存在同样数字精度问题。
例如:
float的精度只能保存7位有效数字(参考C#中float的取值范围和精度分析)
下面这段代码将得到1.01
float number = float.Parse("1.0099999");
Console.WriteLine(number.ToString()); // 1.01

同样的问题double
也存在

如果说上面2个情况平时不容易碰到的话,可以看看下面的例子
0.015四舍五入得到0.01

同样的代码,类型换成double
和decimal
就没有问题了

原因是
Math.Round
无法传入float
类型的参数,float
会隐式转换成double
,但是在转换过程中会丢失精度

3. 关于四舍五入
Math.Round
的默认行为并不是四舍五入
官方文档描述为:舍入到最接近的数字的策略,当数字在两个数字之间的中间时,它将舍入到最接近的偶数。
具体表现是:

如果要使用我们常规理解上的四舍五入,需要使用参数 MidpointRounding.AwayFromZero

4. 建议
- 实际编码中尽量使用
decimal
,避免使用float
-
float
转double
,float
转decimal
,double
转decimal
,使用字符串作为中介,尽可能的保留精度;
如:double.Parse(float.ToString("g9"))
"g17"(double) 或"g9"(float)能尽可能的保留精度,详见标准数字格式字符串,“G”或“g”小结
- 以上部分缺陷在.net5后续版本的.NET中有所改善。
网友评论