小數點處理詳解:切舍、切上、四舍五入
以下對以上小數點處理做詳細的總結說明。
切舍
小數點以下位數切舍,一般會用到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 | 四捨五入 |