四舍五入之银行家算法
对于“四舍五入”的概念,相信大家都熟悉,因为小学三四年级就已经接触过了,常规算法这儿从略。
但对于银行家算法,也许有不少人比较生疏。此前,曾经听说过银行家算法,也知道算法“四舍六入五取偶”的具体实现方法,那就是:(假设对小数部分进行舍入的话),
待舍入的部分恰好为0.5000,则需要看前面一位数的奇偶性,奇数则入,偶数则舍。
举几个例子来描述一下,比如:
11.5000 -> 12
12.5000 -> 12
13.5000 -> 14
14.5000 -> 14
…… ……
尽管知道了这些,但却从来没有深入的想,为什么要这么做。
偶然间,遇到了一个业务方面的问题,有客户反映,一个业务系统产生了两组数据:
第一组,(销售,成本,毛利)=(0.75,0.68,0.08),销售不等于成本和毛利的和,其原因是:
售价50,进价45,数量是0.015,这样计算得到的成本是0.675,毛利是0.075,成本和毛利两个字段都是number(19,2),都五入导致;
第二组,(销售,成本,毛利)=(0.85,0.77,0.09),也是销售不等于成本和毛利的和,原因同样是:
售价50,进价45,数量是0.017,这样计算得到的成本是0.765,毛利是0.085,成本和毛利都五入导致;
这时,才深入思考了一下银行家算法。
按常规的四舍五入算法
…… ……
[0.5,1.5) = 1
[1.5,2.5) = 2
[2.5,3.5) = 3
[3.5,4.5) = 4
[4.5,5.5) = 5
[5.5,6.5) = 6
…… ……
那么,较真的人就会问,为什么是左闭右开,而不采用左开右闭?其实道理是一样的,左闭右开会让恰好为n+0.5的数值全部入,而左开右闭则全部舍。
总之,两者都会使数值有向一端的倾向性。所以,就有人提出银行家算法。
银行家算法
…… ……
(0.5,1.5) = 1
[1.5,2.5] = 2
(2.5,3.5) = 3
[3.5,4.5] = 4
(4.5,5.5) = 5
[5.5,6.5] = 6
…… ……
这样,隔一个n+0.5数值入,隔一个舍,从而使数值趋于均衡.
以上面两组数据为例,得到的结果是:
第一组,(销售,成本,毛利)=(0.75,0.68,0.08)
第二组,(销售,成本,毛利)=(0.85,0.76,0.08)
虽然仍然是不相等,但看整体效果(两行加起来),1.60=1.44+0.16则是相等的.
这儿,说明一下,Oracle的四舍五入是常规算法.而一些开发工具,比如VB、Delphi等等,则是使用银行家算法。