小数点处理详解:切舍、切上、四舍五入
以下对以上小数点处理做详细的总结说明。
切舍
小数点以下位数切舍,一般会用到Math类(位于System命名空间)中的Floor和Truncate方法。 如果是正数的话用哪一个方法结果都是一样的(除了整数部分,小数点以下的相当于0)。最大的不同点在负数。负数的时候,Floor返回的值更小(向负无穷舍入),Truncate返回的值更大(向零舍入为最接近的整数)。
例如:-1.5 Floor(-1.5)=-2、Truncate(-1.5)=-1
VB.NET的Int函数和Floor的返回值是一样的,Fix函数和Truncate的返回值是一样的。在C#中,小数与整数之间变换,使用的就是Truncate方法。
以下是Floor和Truncate方法针对小数-1.5返回值的测试实例:
VB.NET
Dim val As Double = 1.5 Dim ret1 As Double = Math.Floor(val) '1 Dim ret2 As Double = Math.Truncate(val) '1 Dim ret3 As Double = Math.Floor(-val) '-2 Dim ret4 As Double = Math.Truncate(-val) '-1
C# double val = 1.5; double ret1 = Math.Floor(val); //1 double ret2 = Math.Truncate(val); //1 double ret3 = Math.Floor(-val); //-2 double ret4 = Math.Truncate(-val); //-1
切上
小数点以下的位数向整数切(如果小数部分不为0,则整数加1)。使用Math类的Ceiling方法。
不管是正数还是负数都是使用Ceiling,都是“向正无穷舍入”。以下是实例:
VB.NET
Dim val As Double = 1.5 Dim ret1 As Double = Math.Ceiling(val) '2 Dim ret3 As Double = Math.Ceiling(-val) '-1
C#
double val = 1.5; double ret1 = Math.Ceiling(val); //2 double ret3 = Math.Ceiling(-val); //-1
四舍五入
四舍五入(0.5不满切掉,0.5以上整数部加1)使用Math类的Round方法。
但是当小数部分为0.5的时候,Round方法的返回值有时与我们预计的四舍五入的值不一样。按照四舍五入原则,0.5的话应该是切上,但是Round方法的返回值是更接近偶数的。此方法的行为遵循 IEEE 标准 754 的第 4 节。这种舍入有时称为就近舍入或银行家舍入。
例如:Round(1.5)=2、Round(2.5)=2 。
补充:之所以选择这种算法舍入,是因为当进行多次四舍五入累算的时候,这样计算比总是舍入更大的值的误差更小。
Convert类的ToInt32和ToInt64等方法将小数变换成整数也是用的Round这种舍入方法。VB.NET的CInt,CLng整数变换时也是用的Round方法的舍入算法。
VB.NET
Dim ret1 As Double = Math.Round(1.5) '2 Dim ret2 As Double = Math.Round(2.5) '2 Dim ret3 As Double = Math.Round(-1.5) '-2 Dim ret4 As Double = Math.Round(-2.5)
'-2
C#
double ret1 = Math.Round(1.5); //2 double ret2 = Math.Round(2.5); //2 double ret3 = Math.Round(-1.5); //-2 double ret4 = Math.Round(-2.5); //-2
从.NET Framework 2.0开始,Round方法才算可以真正的做四舍五入处理。四舍五入的时候,只要将Round方法的第二个参数设置成MidpointRounding.AwayFromZero就可以了。
VB.NET
Dim ret1 As Double = Math.Round(1.5, MidpointRounding.AwayFromZero) '2 Dim ret2 As Double = Math.Round(2.5, MidpointRounding.AwayFromZero) '3 Dim ret3 As Double = Math.Round(-1.5, MidpointRounding.AwayFromZero) '-2 Dim ret4 As Double = Math.Round(-2.5, MidpointRounding.AwayFromZero) '-3
C#
double ret1 = Math.Round(1.5, MidpointRounding.AwayFromZero); //2 double ret2 = Math.Round(2.5, MidpointRounding.AwayFromZero); //3 double ret3 = Math.Round(-1.5, MidpointRounding.AwayFromZero); //-2 double ret4 = Math.Round(-2.5, MidpointRounding.AwayFromZero); //-3
修正后的Round方法还可以指定舍入位数(从第几位开始舍入)。
补充:现在“切上”方法还没有指定位数舍入。
四舍五入还可以通过类型变换做到。就是将数字类型转化为文字列,然后再将文字列转化为数字类型。
VB.NET
Dim val As Double = 2.5 '小数部0行 Dim s As String = val.ToString("F0") 'Dim s As String = val.ToString("#") Dim ret1 As Double = Double.Parse(s) '3
C#
double val = 2.5; //小数部0行 string s = val.ToString("F0"); //string s = val.ToString("#"); double ret1 = double.Parse(s); //3
总结
以上介绍的方法返回值表如下:
val | -1.8 | -1.5 | -1.2 | 2.2 | 2.5 | 2.8 | (返回值) |
---|---|---|---|---|---|---|---|
Math.Floor(val) | -2 | -2 | -2 | 2 | 2 | 2 | 向负无穷舍入 |
Int(val) (VB.NET) |
-2 | -2 | -2 | 2 | 2 | 2 | |
Math.Truncate(val) | -1 | -1 | -1 | 2 | 2 | 2 | 靠近0舍入 |
(int)val (C#) |
-1 | -1 | -1 | 2 | 2 | 2 | |
Fix(val) (VB.NET) |
-1 | -1 | -1 | 2 | 2 | 2 | |
Math.Ceiling(val) | -1 | -1 | -1 | 3 | 3 | 3 | 向正无穷舍入 |
Math.Round(val) | -2 | -2 | -1 | 2 | 2 | 3 | 就近偶数舍入或银行家舍入 |
Convert.ToInt32(val) | -2 | -2 | -1 | 2 | 2 | 3 | |
CInt(val) (VB.NET) |
-2 | -2 | -1 | 2 | 2 | 3 | |
CType(val, Integer) (VB.NET) |
-2 | -2 | -1 | 2 | 2 | 3 | |
Math.Round(val, MidpointRounding.AwayFromZero) |
-2 | -2 | -1 | 2 | 3 | 3 | 四捨五入 |