一般來說產生誤差主要是因為四捨五入,而金額和單價、數量的小數字數都是有限的。為了避免小數點誤差,要注意以下幾點,否則經常會導致可能出庫時數量出完了,但是金額還不為零的情況出現(不過這種情況很難避免,可以允許使用者做調整,做一些特殊的出入庫單,即允許只有金額、沒有數量的出入庫單,其實這種單據常用的,這是別話)
注意幾個演算法:
1、多用加法、少用乘法。
例如訂單上可能有這麼幾個字段:數量、單價、含稅單價、稅率、金額、稅額、價稅合計。關係如下:
數量×單價=金額
數量×含稅單價=價稅合計;
數量×單價×稅率=稅額;
金額+稅額=價稅合計。
如果這裡你分別用乘法算出金額、稅額、價稅合計,那麼最後很可能就出現金額+稅額不等於價稅合計。這就是我前面說的不能自圓其說了,對於這種情況,你只能用乘法算出其中的兩個,然後第三個,就其中的這兩個金額做加法或者減法得到。例如,先用乘法算出金額和稅額,然後用金額+稅額得出價稅合計;或者先用乘法算出價稅合計和稅額,然後用減法,算出金額。這樣就不會產生誤差。
2、注意用「倒擠」演算法(分攤誤差)即計算尾差
數量乘以單價不等於金額的現象肯定存在,這是允許的,實際手工業務中也是允許的,因為四捨五入的關係,誰也避免不了這個;但是軟體中的做法是:允許誤差,但是誤差們要能自圓其說。時刻牢記要讓「總計數要等於明細數的合計」。例如,總計數是a,總計數被分成了若干份,分別是b、c、d,最後一定要保證:b+c+d=a。
例如,一筆錢是456.87元,要按比例分成三份,第乙份是15.8%,第二份是47.3%,第三份是36.9%,沒有經驗的程式設計師肯定是用總金額分別乘以三個比例,那肯定就有問題了,第乙份:456.87×0.158=72.19。第二份:456.87×0.473=216.1,第三份:456.87×0.369=168.59,那麼把這三個數再合計起來等於多少?72.19+216.1+169.59=456.88。比原來的總額多出了一分錢!這就不平了。所以,碰到這種情況,一定要選擇分攤誤差的地方,一般來說都是用最後一筆分擔誤差,所以叫做倒擠演算法。所以這個例子應該這麼算,前兩筆都用乘法沒問題,到了最後就一定不能總額乘以比例了,而是要用總額減去前面兩筆的合計數,得出第三筆:456.87-(72.19+216.1)=156.58。這樣就對了。
3、每一次乘除法以後立即按照精度四捨五入
一般在軟體系統中會預先讓使用者定義數量、單價、金額的小數字數,這是常識性的做法,但是程式設計師必須在程式中注意四捨五入的時機:在得出乙個結果(數量、單價、金額三者任何乙個)之後,必須立即四捨五入以後,再投入其他運算,如果做了一次乘法、除法以後卻沒有立即根據定義的精度四捨五入,而是直接投入其他運算,最後再四捨五入,那肯定不對。例如:單價:8.49,數量:45.5789,用數量乘以單價得出金額:386.964861,如果你這時候你不把這個金額先四捨五入了再投入其他運算,那麼肯定產生誤差。
4、寫程式注意選擇相同型別的數值型別進行乘除運算。如果不相同型別的數值型別乘除,計算機自己都有可能產生誤差,我就碰到過計算機算出:3.1×2=6.3這種情況
建議做法,在資料型別等都正確的前提下,
(1)使用bigdecimal進行加減乘除
(2)每一次乘除法以後立即按照精度四捨五入,
(3)複雜時結合「倒擠」演算法計算。
可以解決小數(四捨五入)誤差。
「倒擠」演算法例項:
(1)例子:某零件3件乙個包裝盒,每盒**1.00元。
第一次出庫1個零件,出庫金額:0.33元
第二次出庫1個零件,出庫金額:0.33元
第三次出庫1個零件,出庫金額:0.33元
合計:0.99元。這與入庫金額1.00元不符。
(2)「倒擠」演算法實現:最後一次出庫零件金額=1.00-(0.33+0.33)=0.34
有許多方法解決這個問題。例如,採用零件數量和金額獨立存放的方案,建立如下資料表結構
零件編碼 入庫數量 入庫金額 出庫數量 出庫金額 總數量 總金額
=================================
a 3 1.00 3 1.00
a 1 0.33 2 0.67
a 1 0.33 1 0.34
a 1 0.34 0 0.00
DecimalFormat類 小數點計算
decimalformat是numberformat乙個具體的子類,主要是格式化十進位制數。它有各種各樣的設計用於解析和格式化數字中的數字的特性區域設定,包括整數 123 固定點編號 123.4 科學記數法 1.23e4 百分比 12 和貨幣金額 123美元 等。常用到的幾個需求案例 1.保留兩位的...
計算pi小數點後10000位
部落格已搬家到 資料結構課上,老師讓我們計算一下pi的10000位,複習一下物件導向。first try 定義乙個高精度類hp high precision 實現加減乘除,輸入輸出,然後隨便找乙個公式,比如wallis公式,全都用hp進行計算。現實是 大數乘大數或者大數除大數,實在是太慢了。而且wa...
四 資料計算後小數點顯示問題
資料計算後小數點顯示問題 大家都知道,js設計到小數的計算很容易出錯,所以我在專案中改bug的時候發現了乙個好用的方法。numberobject.tofixed num 即乙個有小數的數字物件,通過tofixed num 方法,返回乙個有num個小數字的值。例子 var a 11.123.tofix...