.NET平台 小数舍入规则

常用小数舍入标准简介

1、四舍五入

当舍去位的数值大于等于5时,在舍去该位的同时向前位进一;当舍去位的数值小于5时,则直接舍去该位。

2、银行家舍入(Banker's Round)

所谓银行家舍入法,其实质是一种四舍六入五取偶(又称四舍六入五留双)法。其规则是:当舍去位的数值小于5时,直接舍去该位;当舍去位的数值大于等于6时,在舍去该位的同时向前位进一;当舍去位的数值等于5时,如果前位数值为奇,则在舍去该位的同时向前位进一,如果前位数值为偶,则直接舍去该位。

下面举.NET中处理decimal类型的一个例子:

 

using System; 
using System.Collections.Generic; 
using System.Text; 
 
namespace ConsoleApplication2 
{ 
        class Program 
        { 
                static void Main(string[] args) 
                { 
                        //Floor方法向负无穷方向舍入为最接近的整数 
                        Console.WriteLine(decimal.Floor(-1.3m)); //-2 
                        Console.WriteLine(decimal.Floor(3.5m)); //3 
                        Console.WriteLine(decimal.Floor(4m));     //4 
 
                        //Truncate方法向零方向舍入为整数 
                        Console.WriteLine(decimal.Truncate(-1.3m));//-1 
                        Console.WriteLine(decimal.Truncate(3.5m));//3 
                        Console.WriteLine(decimal.Truncate(4m));    //4 
 
                        //实现正的decimal数值的四舍五入,则必须用下面的技巧,保留到小数点后2位,就用100,保留到小数点后3位就用1000,依次类推 
                        decimal a = 8.335m, b = 8.345m; 
                        Console.WriteLine(decimal.Truncate(a * 100 + 0.5m) / 100); //8.34 
                        Console.WriteLine(decimal.Truncate(b * 100 + 0.5m) / 100); //8.35 
 
                        //实现负的decimal数值的四舍五入,则必须用下面的技巧,保留到小数点后2位,就用100,保留到小数点后3位就用1000,依次类推 
                        decimal c = -8.335m, d = -8.345m; 
                        Console.WriteLine(decimal.Truncate(c * 100 - 0.5m) / 100); //8.34 
                        Console.WriteLine(decimal.Truncate(d * 100 - 0.5m) / 100); //8.35 
                        Console.WriteLine(); 
                } 
        } 
}       

从上面这个例子看出,decimal类型的Floor方法和Truncate方法比较特殊,而如果想实现decimal类型的四舍五入,这里用的是Truncate方法和数学计算的形式实现的四舍五入。

事实上System.Double结构和System.Single结构中本身没提供Floor方法和Truncate方法,但是,System.Math结构却提供了double类型对应的Floor方法和Truncate方法。所以可以利用Math结构的Floor方法和Truncate方法实现对double类型的小数处理以及四舍五入,功能和System.Decimal结构提供的Floor方法和Truncate方法一样,而float类型可以隐式转换为double类型,来实现float类型的小数处理以及四舍五入。另外,Math结构的Floor方法和Truncate方法还有对应的处理decimal类型的重载形式,功能和System.Decimal结构提供的Floor方法和Truncate方法一样。

 

System.Decimal结构以及System.Math还提供了一个Round方法,这就讲到到舍入的规则了。

System.Decimal的Round方法有四种重载形式,其中有三种重载形式最经常用。同样,System.Math结构也提供了Round方法,它和System.Decimal的Round方法区别是,System.Math结构的Round方法不仅提供了处理decimal类型的版本,而且还提供了处理double类型的版本,所以System.Math结构的Round方法有八种重载形式。

如果你看完了下面这个例子,那么.NET平台中怎么实现银行家舍入和四舍五入也便搞懂了。

 

using System; 
using System.Collections.Generic; 
using System.Text; 
 
namespace ConsoleApplication2 
{ 
        class Program 
        { 
                static void Main(string[] args) 
                {     
                        //四舍六入五取偶 
                        Console.WriteLine(decimal.Round(3.5m));
               //四舍六入五取偶 
                        Console.WriteLine(decimal.Round(4.5m));
               //四舍六入五取偶 
                        Console.WriteLine(decimal.Round(4.6m));
               //四舍六入五取偶 
                        Console.WriteLine(decimal.Round(3.6m));
               //四舍六入五取偶 
                        Console.WriteLine(decimal.Round(4.7m));
                        Console.WriteLine(); 

               //四舍六入五取偶 
                        Console.WriteLine(Math.Round(3.5m));
               //四舍六入五取偶 
                        Console.WriteLine(Math.Round(4.5m));
               //四舍六入五取偶 
                        Console.WriteLine(Math.Round(4.6m));
               //四舍六入五取偶 
                        Console.WriteLine(Math.Round(3.6m));
               //四舍六入五取偶 
                        Console.WriteLine(Math.Round(4.7m));
                        Console.WriteLine(); 

               //四舍六入五取偶 
                        Console.WriteLine(Math.Round(3.5));
               //四舍六入五取偶 
                        Console.WriteLine(Math.Round(4.5));
               //四舍六入五取偶 
                        Console.WriteLine(Math.Round(4.6));
               //四舍六入五取偶 
                        Console.WriteLine(Math.Round(3.6));
               //四舍六入五取偶 
                        Console.WriteLine(Math.Round(4.7));
                        Console.WriteLine(); 
 
                        //四舍六入五取偶
               Console.WriteLine(decimal.Round(0.125m,2));
               //四舍六入五取偶 
                        Console.WriteLine(decimal.Round(0.135m, 2));
               //四舍六入五取偶 
                        Console.WriteLine(decimal.Round(0.126m, 2));
               //四舍五入
                        Console.WriteLine(decimal.Round(-3.105m, 2, MidpointRounding.AwayFromZero)); 
               //四舍五入
                        Console.WriteLine(decimal.Round(-0.5m, 0, MidpointRounding.AwayFromZero)); 
                        Console.WriteLine(); 

               //四舍六入五取偶 
                        Console.WriteLine(Math.Round(0.125m, 2));
               //四舍六入五取偶
               Console.WriteLine(Math.Round(0.135m, 2)); 
               //四舍六入五取偶
               Console.WriteLine(Math.Round(0.126m, 2));
               //四舍五入
               Console.WriteLine(Math.Round(-3.105m, 2, MidpointRounding.AwayFromZero));
               //四舍五入
               Console.WriteLine(Math.Round(-0.5m, 0, MidpointRounding.AwayFromZero));
               Console.WriteLine(); 
               //四舍六入五取偶  
               Console.WriteLine(Math.Round(0.125, 2));
                        //四舍六入五取偶 
               Console.WriteLine(Math.Round(0.135, 2));
                        //四舍六入五取偶 
               Console.WriteLine(Math.Round(0.126, 2));
                        //四舍五入
               Console.WriteLine(Math.Round(-3.105, 2, MidpointRounding.AwayFromZero)); 
                        //四舍五入
               Console.WriteLine(Math.Round(-0.5, 0, MidpointRounding.AwayFromZero)); 
                        Console.WriteLine(); 
                } 
        } 
}             

注意:小数默认的类型是double类型,所以凡是末尾没加mM的小数都是double类型。

System.DecimalRound方法和System.Math结构的Round方法默认情况下,都是采用的银行家舍入,即四舍六入五取偶,其中带一个参数的重载和带两个参数的重载形式下,默认都是银行家舍入。比较特殊的是带三个参数的Round方法,它的第三个参数是MidpointRounding枚举类型,MidpointRounding枚举类型定义了两个枚举值,为了实现四舍五入,我们这里使用的是MidpointRounding.AwayFromZero这个值。MidpointRounding.AwayFromZero枚举值的真正意思是:当一个数字是其他两个数字的中间值时,会将其舍入为两个值中绝对值较大的值。

所以我们既可以使用Round方法的前两种重载形式实现银行家舍入,也可以使用带三个参数的Round方法实现四舍五入,但枚举值必须使用MidpointRounding.AwayFromZero,而不能使用MidpointRounding.ToEven

posted on 2012-09-29 16:57  ※WYF※  阅读(1830)  评论(0编辑  收藏  举报