C# Round()函数,数值四舍五入取整方式
今天在项目中偶然遇到使用decimal.Round()函数对decimal值进行取2位小数时,0.995的值为1. 代码如下:
decimal newVal = decimal.Round((decimal)0.995, 2);
运行后newVal=1. 因为是涉及到打折的问题,所以预期期望应该是0.99。于是找了下资料,读了MSDN的文档,对decimal取整的用法大致熟悉了,遂成此文,用于参考。
decimal.Round()有四个重载方法:
- decimal.Round(decimal)
- decimal.Round(decimal, Int32)
- decimal.Round(decimal, Int32, MidpointRounding)
- decimal.Round(decimal, MidpointRounding)
1. decimal.Round(decimal)
public static decimal Round(
decimal d
)
返回最接近d的整数,如果d在相邻的两个整数之间(及为X.5),则返回其中一个为偶数的值。如,8.5->8, 7.5->8.
代码示例如下:
using System;
public class Example
{
public static void Main()
{
for (decimal value = 100m; value <= 102m; value += .1m)
Console.WriteLine("{0} --> {1}", value, Decimal.Round(value));
}
}
// The example displays the following output:
// 100 --> 100
// 100.1 --> 100
// 100.2 --> 100
// 100.3 --> 100
// 100.4 --> 100
// 100.5 --> 100
// 100.6 --> 101
// 100.7 --> 101
// 100.8 --> 101
// 100.9 --> 101
// 101.0 --> 101
// 101.1 --> 101
// 101.2 --> 101
// 101.3 --> 101
// 101.4 --> 101
// 101.5 --> 102
// 101.6 --> 102
// 101.7 --> 102
// 101.8 --> 102
// 101.9 --> 102
// 102.0 --> 102
2. decimal.Round(decimal, Int32)
public static decimal Round(
decimal d,
int decimals
)
decimals范围:[0,28]
返回精度为decimals,对d进行取整的数。实际上该函数对精度还是会使用取整操作,相当于调用Round(decimal, Int32, MidpointRounding.ToEven).当所指定精度后一位数刚好在两个数中间时,会更加该数值的奇偶性来取舍。 如当精度为2时,2.345是2.34,而2.355则是2.36.这个处理过程是被广为接受的取偶法或者银行取舍法。这种方式在最大程度上避免了四舍五入带来的偏差。
实例代码如下:
using System;
class Example
{
public static void Main()
{
// Define a set of Decimal values.
decimal[] values = { 1.45m, 1.55m, 123.456789m, 123.456789m,
123.456789m, -123.456m,
new Decimal(1230000000, 0, 0, true, 7 ),
new Decimal(1230000000, 0, 0, true, 7 ),
-9999999999.9999999999m,
-9999999999.9999999999m };
// Define a set of integers to for decimals argument.
int[] decimals = { 1, 1, 4, 6, 8, 0, 3, 11, 9, 10};
Console.WriteLine("{0,26}{1,8}{2,26}",
"Argument", "Digits", "Result" );
Console.WriteLine("{0,26}{1,8}{2,26}",
"--------", "------", "------" );
for (int ctr = 0; ctr < values.Length; ctr++)
Console.WriteLine("{0,26}{1,8}{2,26}",
values[ctr], decimals[ctr],
Decimal.Round(values[ctr], decimals[ctr]));
}
}
// The example displays the following output:
// Argument Digits Result
// -------- ------ ------
// 1.45 1 1.4
// 1.55 1 1.6
// 123.456789 4 123.4568
// 123.456789 6 123.456789
// 123.456789 8 123.456789
// -123.456 0 -123
// -123.0000000 3 -123.000
// -123.0000000 11 -123.0000000
// -9999999999.9999999999 9 -10000000000.000000000
// -9999999999.9999999999 10 -9999999999.9999999999
3. Decimal.Round Method (Decimal, Int32, MidpointRounding)
public static decimal Round(
decimal d,
int decimals,
MidpointRounding mode
)
返回指定精度的四舍五入的值,如果是中间值时,根据参数来mode来进行取舍。
前两个参数跟上两个方法无异,主要来说一下MidpointRounding结构体。
MidpointRounding结构体有两个值,用于在取整时来判断是进位还是舍值的情形:
- AwayFromZero:远离0的取法,如4.5取一位应为5,-4.5->-5;
- ToEven: 取偶数法,如4.5取以为为4。
具体的算法可参见以下例子:
/*
This code example produces the following results:
3.4 = Math.Round( 3.45, 1)
-3.4 = Math.Round(-3.45, 1)
3.4 = Math.Round( 3.45, 1, MidpointRounding.ToEven)
3.5 = Math.Round( 3.45, 1, MidpointRounding.AwayFromZero)
-3.4 = Math.Round(-3.45, 1, MidpointRounding.ToEven)
-3.5 = Math.Round(-3.45, 1, MidpointRounding.AwayFromZero)
*/
4. Decimal.Round Method (Decimal, MidpointRounding)
public static decimal Round(
decimal d,
MidpointRounding mode
)
该方法是四舍五入取整法,mode参数用于指定中间值的取法。
总结:
总的来说,一般情况下,我们可以直接使用Round(decimal)和Round(decimal,Int32)来进行取整和小数的精度计算。
因为这两个方法的默认MidpointRounding属性已经够满足我们大部分的使用场景。对于特殊性的MidpointRounding.AwayFromZero的方式,视具体情况而定。
另外,Math.Round()方法笔者没有详细去考证,当可以推测其用法与本文所述的decimal.Round()用法应该是一致的。