经常看到有人提出 Round 函数的问题,很多人都认为这个函数就是四舍五入算法,其实是错误的。
在 VB, VBScript, C#, J#, T-SQL 中 Round 函数都是采用 Banker's rounding(银行家舍入)算法,即四舍六入五取偶。详细的说是这样:四舍六入五考虑, 五后非零就进一, 五后皆零看奇偶, 五前为偶应舍去, 五前为奇要进一. 事实上这也是 IEEE 规定的舍入标准。因此所有符合 IEEE 标准的语言都是采用这一算法的。
虽然“四舍五入”是我国最早提出的算法,值得我们自豪,但不能因此就认为它始终是先进的。毕竟它已经有近二千年历史了(大约一千七百多年前,天文学家杨伟就已明确提出了“四舍五入法”)。
四舍五入算法逢五就要进位,带来的问题就是结果偏大,尤其是在大量的数据统计中。4舍6入没有什么特别,就是5 比较特殊,如果5舍就会偏小,如果5入就会偏大,Banker 舍入法是取最接近的偶数,这样就比四舍五入准确性高,我们看下面的例子。
原始数据 四舍五入 Banker 舍入
1.1249 1.12 1.12
1.1248 1.12 1.12
1.1252 1.13 1.12
1.1250 1.13 1.12
excel中round函数的使用方法 1.1354 1.14 1.14
1.1351 1.14 1.14
1.1352 1.14 1.14
1.1353 1.14 1.14
1.1361 1.14 1.14
1.1360 1.14 1.14
----------------------------------------------------------------
平均值 1.1313 1.134 1.132
这组原始数据它们的平均值是1.1313;如果我们按四舍五入保留两位小数,它们的平均值是1.134,误差是+0.0027;如果我们采用 Banker 舍入,结果是1.1320,误差是+0.0007。可以看出四舍五入的误差要大得多。而在金融计算和统计中是精度是非常重要的,这也是 Banker 舍入的名称的由来,银行家是不喜欢四舍五入的。
四舍五入是我上小学时数学课程的内容,大多数中国人都坚信舍入小数时应该使用这个算法。所幸据说现在的小学数学课程已经将 Banker's rounding 正式写入课本。希望以后的孩子大概不会再有现在的问题了。
关于编程中 Round 函数和 Banker 舍入的信息,可以参考微软的 Knowledge Base:
Q194983 PRB: Round Function Different in VBA 6 and Excel Spreadsheet
Q196652 HOWTO: Implement Custom Rounding Procedures
---------------------------------------------------------------------------------------------------------
另外,我们还可能碰到这样的问题
MATH.ROUND(3.225,2) 结果是 3.22
MATH.ROUND(1.225,2) 结果是 1.23
这是在中的使用 Round 函数的两个例子,我们知道中的Round 函数使用的就是Banker's rounding(银行家舍入)算法。按前面的理解,五前为偶应舍去,3.225 保留2位小数确实是3.22,1.225同样应该符合 五前为偶应舍去 的原则,可是为什么结果是1.23呢?
其实,这是由于数据类型精度的问题导致的,这是由于浮点数(double或float)的不精确造成的,1.225 如果作为浮点数常量,在机器内部存储时,可能是 1.2250000000000000000000001,按照 五后非零就进一 原则,就被舍入为 1.23 了。如果用 System.Decimal 数据类型,就没有这个问题了,例如:
在.Net中 ?Math.Round(CDec(1.225), 2) 结果就是 1.22 了,所以出现这种情况,并不是Round函数有错,而是我们在编程时应该注意数据精度的问题。
但是在VBScript中并没有Decimal数据类型,这时我们可以用Currency来处理。例如:
VBScript中 Round(1.225,2) 结果就是 1.23
Round(CCur(1.225),2) 结果就是 1.22
但是值得注意的是VBScript中的Currency类型只能处理4位小数,其取值范围是 922,337,203,685,477.5808 到 922,337,203,685,477.5807。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论