不要讓四捨五入虧了一方

2021-02-13 程序設計及計算機基礎學習空間

重溫一個小學數學問題:四捨五入。四捨五入是一種近似精確的計算方法,在Java 5之前,我們一般是通過使用Math.round來獲得指定精度的整數或小數的,這種方法使用非常廣泛,代碼如下:

public class Client {  

     public static void main(String[] args) {  

          System.out.println("10.5近似值:" + Math.round(10.5));  

          System.out.println("-10.5近似值:"+ Math.round(-10.5));  

     }  

輸出結果為:

10.5近似值:11  

-10.5近似值:-10 

這是四捨五入的經典案例,也是初級面試官很樂意選擇的考題,絕對值相同的兩個數字,近似值為什麼就不同了呢?這是由Math.round採用的捨入規則所決定的(採用的是正無窮方向捨入規則,後面會講解)。我們知道四捨五入是有誤差的:其誤差值是捨入位的一半。我們以捨入運用最頻繁的銀行利息計算為例來闡述該問題。

我們知道銀行的盈利渠道主要是利息差,從儲戶手裡收攏資金,然後放貸出去,其間的利息差額便是所獲得的利潤。對一個銀行來說,對付給儲戶的利息的計算非常頻繁,人民銀行規定每個季度末月的20日為銀行結息日,一年有4次的結息日。

場景介紹完畢,我們回過頭來看四捨五入,小於5的數字被捨去,大於等於5的數字進位後捨去,由於所有位上的數字都是自然計算出來的,按照概率計算可知,被捨入的數字均勻分布在0到9之間,下面以10筆存款利息計算作為模型,以銀行家的身份來思考這個算法:

四舍。

捨棄的數值:0.000、0.001、0.002、0.003、0.004,因為是捨棄的,對銀行家來說,就不用付款給儲戶了,那每捨棄一個數字就會賺取相應的金額:0.000、0.001、0.002、0.003、0.004。

五入。

進位的數值:0.005、0.006、0.007、0.008、0.009,因為是進位,對銀行家來說,每進一位就會多付款給儲戶,也就是虧損了,那虧損部分就是其對應的10進位補數:0.005、0.004、0.003、0.002、0.001。

因為捨棄和進位的數字是在0到9之間均勻分布的,所以對於銀行家來說,每10筆存款的利息因採用四捨五入而獲得的盈利是:

0.000 + 0.001 + 0.002 + 0.003 + 0.004 - 0.005 - 0.004 - 0.003 - 0.002 - 0.001 = -0.005 

也就是說,每10筆的利息計算中就損失0.005元,即每筆利息計算損失0.0005元,這對一家有5千萬儲戶的銀行來說(對國內的銀行來說,5千萬是個很小的數字),每年僅僅因為四捨五入的誤差而損失的金額是:

public class Client {  

     public static void main(String[] args) {  

          //銀行帳戶數量,5千萬  

          int accountNum =5000*10000;  

          //按照人行的規定,每個季度末月的20日為銀行結息日  

          double cost = 0.0005 * accountNum * 4 ;  

          System.out.println("銀行每年損失的金額:" + cost);  

     }  

輸出的結果是:「銀行每年損失的金額:100000.0」。

即每年因為一個算法誤差就損失了10萬元,事實上以上的假設條件都是非常保守的,實際情況可能損失得更多。那各位可能要說了,銀行還要放貸呀,放出去這筆計算誤差不就抵消掉了嗎?不會抵銷,銀行的貸款數量是非常有限的,其數量級根本沒有辦法和存款相比。

這個算法誤差是由美國銀行家發現的(那可是私人銀行,錢是自己的,白白損失了可不行),並且對此提出了一個修正算法,叫做銀行家捨入(Banker's Round)的近似算法,其規則如下:

捨去位的數值小於5時,直接捨去;

捨去位的數值大於等於6時,進位後捨去;

當捨去位的數值等於5時,分兩種情況:5後面還有其他數字(非0),則進位後捨去;若5後面是0(即5是最後一個數字),則根據5前一位數的奇偶性來判斷是否需要進位,奇數進位,偶數捨去。

以上規則匯總成一句話:四捨六入五考慮,五後非零就進一,五後為零看奇偶,五前為偶應捨去,五前為奇要進一。我們舉例說明,取2位精度:

round(10.5551) = 10.56  

round(10.555)  = 10.56  

round(10.545)  = 10.54 

要在Java 5以上的版本中使用銀行家的捨入法則非常簡單,直接使用RoundingMode類提供的Round模式,或Math.rint方法即可,示例代碼如下:

public class Client {  

     public static void main(String[] args) {  

          //存款  

          BigDecimal d = new BigDecimal(888888);  

          //月利率,乘3計算季利率  

          BigDecimal r = new BigDecimal(0.001875*3);  

          //計算利息  

          BigDecimal i = d.multiply(r).setScale(2, RoundingMode.HALF_EVEN);  

          System.out.println("季利息是:"+i);  

     }  

在上面的例子中,我們使用了BigDecimal類,並且採用setScale方法設置了精度,同時傳遞了一個RoundingMode.HALF_EVEN參數表示使用銀行家捨入法則進行近似計算,BigDecimal和RoundingMode是一個絕配,想要採用什麼捨入模式使用RoundingMode設置即可。目前Java支持以下七種捨入方式:

ROUND_UP: 遠離零方向捨入。向遠離0的方向捨入,也就是說,向絕對值最大的方向捨入,只要捨棄位非0即進位。

ROUND_DOWN:趨向零方向捨入。向0方向靠攏,也就是說,向絕對值最小的方向輸入,注意:所有的位都捨棄,不存在進位情況。

ROUND_CEILING:向正無窮方向捨入。向正最大方向靠攏,如果是正數,捨入行為類似於ROUND_UP;如果為負數,則捨入行為類似於ROUND_DOWN。注意:Math.round方法使用的即為此模式。

ROUND_FLOOR:向負無窮方向捨入。向負無窮方向靠攏,如果是正數,則捨入行為類似於 ROUND_DOWN;如果是負數,則捨入行為類似於 ROUND_UP。

HALF_UP: 最近數字捨入(5進)。這就是我們最最經典的四捨五入模式。

HALF_DOWN:最近數字捨入(5舍)。在四捨五入中,5是進位的,而在HALF_DOWN中卻是捨棄不進位。

HALF_EVEN :銀行家算法。Math.rint方法使用的即為此模式。

在普通的項目中捨入模式不會有太多影響,可以直接使用Math.round方法,但在大量與貨幣數字交互的項目中,一定要選擇好近似的計算模式,儘量減少因算法不同而造成的損失。

資料引用:http://www.cnblogs.com/DreamDrive/p/5424962.html

相關焦點

  • 生活的「四捨五入」
    比如買蘋果的時候,應該給9.40元,我會自動「四捨五入」,給賣家9元。工作中,我也很愛計較到小數點以後的數字。我是教師,教學成績是評價我們工作的重要標準。每次考試前,我都明裡暗裡跟同事較勁,希望能夠超過他們。有次期末考試,我的教學成績比同事高出0.8分,我得意地跟朋友說:「我的成績是第一名,比別人高了1分!」多年來,我一直在做著這樣的計算。
  • ROUND(四捨五入)計算指定位數四捨五入某個數字
    ROUND計算指定位數四捨五入某個數字大家好,這節課我們來學習一下Round函數。ROUND,這個函數對於要計算錢的工作崗位尤其重要,人資計算稅金,財務計算工資,經常都會碰到小數點後幾位的數字,一般的做法就是直接在格式裡修改為保留2位小數。但是這個做法會有一個很大的隱患。
  • Excel四捨五入不再出錯
    當我們在使用Excel電子表格製作數據報表時,為了避免大量小數的運算,常常會用到四捨五入的方法,但是這樣做可能會造成數值運算的誤差,而且不容易找到原因。如果對計算出的數值精度要求不高,可以在Excel菜單欄上點擊「格式」 -「單元格」,在「單元格格式」窗口中設置「小數位數」的數字(如圖1),決定保留幾位小數,超過的位數就會被舍掉。
  • 四捨五入就是一個億是什麼梗 四捨五入就是一個億梗出自哪裡
    四捨五入一個億是什麼意思,網上最近總有人說四捨五入一個億的梗,那麼四捨五入一個億是什麼意思,出自哪裡呢?  四捨五入一個億是什麼意思  四捨五入就是大於5的可以進1,而小於5的就舍掉,相信這個數學題大家還是算的過來的。
  • excel四捨五入函數怎麼用 excel四捨五入函數的使用方法
    excel四捨五入函數怎麼用  函數格式:ROUND(數值或數值單元格,要保留的位數),  例:ROUND(19.531,2) 表示對19.531四捨五入,保留2位小數,結果為19.53,  如圖,對A1單元格進行四捨五入(保留兩位小數),結果顯示在B1單元格裡,  操作步驟如下:
  • excel四捨五入函數怎麼用
    真不知道四捨五入是誰發明的,好像小學就開始學習它了,日常買個菜什麼的老闆也不捨得四捨五入最頭省個2,3毛。到時在發工資時常講究個四捨五入,都被公司給摳了。小數點太多了我們都會使用四捨五入的方法來統一保留幾位小數點,這樣也方便計算,一般都是在最後的總數值上進入處理的,不然數據出入就會變得很大了。EXCEL中四捨五入可以使用ROUND函數,ROUND(Number, Num_Digits)按指定的位子對數值進行四捨五入。
  • EXCEL函數基礎之四捨五入、四捨六入及隨機函數
    =FLOOR(2.53,0.2)=2.4 具體區別如下 * TRUNC函數: =TRUNC(number,num_digits) 按給出的小數位數進行截尾。: 如果數值 number 除以基數的餘數大於或等於基數的一半,則函數 MROUND 向遠離零的方向捨入。
  • 如何在 Python 裡面精確四捨五入?
    那 Python 是如何處理浮點數的四捨五入問題的呢?今天分享的文章,對此展開了深入的剖析。本文作者 kingname,來自網易,公眾號「未聞Code」。如需轉載,請聯繫作者。今天又有一個Python初學者被中文技術博客中的垃圾文章給誤導了。這位初學者的問題是:在Python中,如何精確地進行浮點數的四捨五入,保留兩位小數?
  • 函數四捨五入使用技巧
    在實際工作的數學運算中,特別是財務計算中常常遇到四捨五入的問題。雖然,excel的單元格格式中允許定義小數位數,但是在實際操作中,我們發現,其實數字本身並沒有真正的四捨五入,只是顯示結果似乎四捨五入了。如果採用這種四捨五入方法的話,在財務運算中常常會出現幾分錢的誤差,而這是財務運算不允許的。那是否有簡單可行的方法來進行真正的四捨五入呢?
  • excel四捨五入函數是什麼?怎樣使用?
    今天小編要介紹的是excel四捨五入函數,四捨五入函數在數據的處理中也是很常用的。二、excel四捨五入函數excel中的四捨五入函數是ROUND,該函數的語法格式是:ROUND(數值或數值單元格,保留小數的位數)。
  • 學習四捨五入最簡單的方法?
    1)使用在線計算器四捨五入數字:我們生活在一個時代,在這個時代,先進的技術使我們的工作變得更加輕鬆。現在,我們可以找到許多足夠聰明的在線工具,可以快速,準確地計算複雜的數學運算。 這樣的工具之一就是捨入計算器,該計算器專門用於將數字四捨五入到十,幾百,幾千,幾萬,幾百萬甚至十億。
  • 買單「四捨五入」成商家潛規則
    記者通過調查了解到,除街邊小店外,超市、加油站、商場也存在買單「四捨五入」的潛規則。 超市、加油站等均存在此種現象 5月25日,網友「麥熊哈哈」發帖稱,在仙遊二中附近的凡點飾品連鎖店消費11.9元,收銀小妹卻要求多收1毛錢,「化整為零」。他既氣憤又不解,「哪有這樣做買賣的?那一毛錢就是我的,怎麼可以私自做主不給呢?」
  • 餐廳結帳「四捨五入」?不僅違規也缺乏誠信
    對此,服務員振振有詞解釋道:「按本店的規定,四捨五入之後就是104元了。」昨天,記者在北京路、解放路等多家餐飲店展開調查,發現所謂「四捨五入」的記帳潛規則屢見不鮮,一些標榜「打折」的餐飲店,「四捨五入」後的價格與優惠前的原價竟然一致。業內人士表示,餐廳四捨五入的結帳方式,不僅違反了就餐服務合同,也未盡誠信義務。
  • 生活中的「四捨五入」法
    生活中的「四捨五入」法雖然已經立秋,但面對誘人的沙瓤西瓜,我顯然沒有多少抵抗力一旁的小外甥顯然也聽到了小夥子的話,抬頭想我提問:「舅舅,20斤5兩,『四捨五入』是21斤,應該收21塊錢沒錯啊?」聽到這裡,我突然一愣,思維定格在了小學五年級的一節數學課上,當時課堂教學內容已經講完了,面對同學們認真做題的場面,高林堂老師語重心長地對我們說:「同學們,我們今天所學習的『四捨五入』法能幫助我們解決試卷上的難題,讓我們獲取分數。
  • 打的費「四捨五入」的行規該成老黃曆了
    但近日,四川內江有網友反映,稱自己用微信支付計程車費用時,仍遭遇零頭「四捨五入」行規,甚至有4角零錢未被「舍」掉,而被「入」為5角的情況。計程車收費「四捨五入」,這確實是計程車行業存在多年的行規,很多城市都這樣。不僅如此,一些地方直接以紅頭文件形式明確計程車行業車費結算實行「四捨五入」機制。
  • Excel:乘積求和和四捨五入函數
    四、SUMPRODUCT函數——乘積求和SUMPRODUCT的漢語含義就是——乘積求和,顧名思義就是對兩組數據先做乘法後求和
  • Excel如何把小數點四捨五入取整?
    在Excel表格中整理數據的時候,為了避免大量的小數點,通常都會採用四捨五入的方式,減少小數點,這樣工作起來也比較方便,還能提高工作效率。Excel如何把小數點四捨五入取整呢?下面一起看下解決的方法。操作步驟如下:方法一:四捨五入函數ROUND函數格式:ROUND(數值或數值單元格,要保留的位數)例:ROUND(20.156,2) 表示對20.156四捨五入,保留2位小數,結果為20.16
  • Excel也會「作假」—真正實現四捨五入
    在我們日常的實際工作中,特別是財務計算中常常遇到四捨五入的問題。雖然,Excel的單元格格式中允許定義小數位數,但是在實際操作中我們發現,其實數字本身並沒有真正實現四捨五入。如果採用這種四捨五入的方法,在財務運算中常常會出現誤差,而這是財務運算所不允許的。
  • js 四捨五入 js取整數
    做網頁開發的時候,經常需要將一些數據進行取整操作,比如:向上取整,向下取整,四捨五入取整等等,那麼js是怎麼處理的呢?那麼我們先在網頁上面放一個輸入框,四個按鈕,分別測試:「1.丟棄小數部分,保留整數部分「 、「2.向上取整,有小數就整數部分加1 「、」3.四捨五入.」 、「4.向下取整」,分別點擊按鈕的時候,我們將做以上四個取整測試,創建輸入框和點擊按鈕的HTML代碼如下:<!
  • 專業英語—英文中的「四捨五入」怎麼說
    四捨五入是一種精確度的計數保留法,意即把小數點後面的數字四捨五入,英文的表達是round up, up有時可以省略, 直接說round to。Round up:To increase an exact figure to the next highest whole number 把數向上取整數,比如:round up to the nearest integer 四捨五入到最接近的整數rounding up days or months to the nearest year 將日期或月份四捨五入到最接近的年份