银行家舍入VS四舍五入(下):.NET发现之旅(四)
接上节
这一节继续讨论银行家舍入和四舍五入
三,自己动手开发四舍五入组件
事实上四舍五入在很多项目中还经常使用,所以我们可以动手开发一个这样的组件,以后可以在多个项目中重用。
在开发四舍五入组件之前,先要搞明白doulbe类型和decimal类型的精度问题,这也是很多学员迷糊的地方。
根据double类型和decimal类型表示的最大值和最小值的区间,我们会发现double类型的值最多能显示出15个有意义的数字(不包裹小数点),而decimal类型的值最多能显示出来29个有意义的数字(不包裹小数点),从这里也能看出为什么decimal类型又成为货币类型,因为它足够精确。如果double类型的值超过15个数字,就会截断,同样如果deciaml类型的值如果超过29个数字,就会截断。但截断的时候会四舍五入。例如:
double MyDouble1 = 123456789.34654654101104153453413212;
double MyDouble2 = 1234567890.34654654101104153453413212;
decimal MyDecimal1 = 123456789.34654654101104153453513212m;
decimal MyDecimal2 = 1234567890.34654654101104153453513212m;
Console.WriteLine(MyDouble1);//double输出时最多有15个数字。
Console.WriteLine(MyDouble2);//double输出时最多有15个数字。
Console.WriteLine(MyDecimal1);//decimal输出时最多有29个数字。
Console.WriteLine(MyDecimal2);//decimal输出时最多有29个数字。
Console.WriteLine();
同样采用生成格式的办法来输出double类型和deciaml类型也会截断,但是根据格式的长度,会面会自动补零。例如:
double i = -12345.67897456345;
Console.WriteLine(string.Format("{0:f" + 99 + "}", i));//大于等于100时出错 decimal j = -12345.67897456345m;
Console.WriteLine("{0:f" + 99 + "}", j);//大于等于100时出错
Console.WriteLine();
上面这个两段代码的打印结果如下图
那么为什么最长是15个数字和29个数字呢?
因为Double 值类型表示一个值介于 -1.79769313486232e308 和 +1.79769313486232e308 之间的双精度 64 位数字,以及 +0 或-0、PositiveInfinity、NegativeInfinity和非数字(NaN)。如果你耐住性子数数最小值和最大值的位数,你发现时15个数字。而Decimal 值类型表示从正 79,228,162,514,264,337,593,543,950,335 到负 79,228,162,514,264,337,593,543,950,335 之间的十进制数。Decimal 值类型适用于要求使用大量有效的整数及小数位数并且没有舍入错误的财务计算。同样,如果你耐住性子数数最小值和最大值的位数,你发现是29个数字。
这个组件的思想是利用Truncate方法和数学计算开发的,当然也可以利用封装Round方法开发。因为这个组件是以前我在项目中用的,所以就没采用Round方法。
源代码下载和dll下载在后面。这个组件可以对单个double和decimal进行四舍五入,也可以同时对N个double和decimal进行四舍五入,保留小数点后面多少位没有限制,但是必须要明白,double不能超过15个数字和decimal不能超过29数字的本质。类关系图如下图
最后PS:目前银行家算法已经写入小学的教科书,不懂的可以向小学生请教!呵呵
附件:http://down.51cto.com/data/2352523
本文转自terryli51CTO博客,原文链接: http://blog.51cto.com/terryli/154848,如需转载请自行联系原作者