关于不能够精确的对浮点数进行运算的问题
http://edu.eoe.cn/?? 在線課堂
昨天看到一篇帖子說了幾個很明顯的簡單的浮點的運算,計算機都會算錯。
我引過來給大家看看:‘
運行代碼:
大家可以自己新建一個工程來試試,結果如下:
0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999這就很神奇了,0.05+0.01很明顯是0.06嘛,但是為什么會變成0.060000000000000005?
是不是計算器太弱智?真是計算機就不靠譜了?
當然不是的。主要是因為java中的簡單類型并不適用于對浮點的精確計算。不光是JAVA ,其它語言也存在同樣的問題。
雖然現在CPU都支持浮點的運算了,但是CPU在處理的時候,也是先把浮點數(float , double)轉成整數再轉成二進制,然后進行操作,如果有取余,會有不同的取余方式。
再加上運算完成后,再多二進制轉成上層的浮點,又會有一些取舍。就造成了呈現出來時的簡單明顯的錯誤 。
所以說,一般float和double用來做科學計算或者是工程計算,在一般對精度要求較高的地方(如商業),我們會用到BCD碼或者是java.math.BigDecimal。
BSD碼(Binary-Coded Decimal),稱BCD碼或二-十進制代碼,亦稱二進碼十進數。是一種二進制的數字編碼形式,用二進制編碼的十進制代碼。
大家對這個有興趣的可以深入研究一下,今天我們主要講的是BigDecimal類。因為我們在做項目的時候,尤其是對商業項目時,我們不可能還去搞個什么BSD碼,可以直接利用BigDecimal類來完成我們的需求。
BigDecimal 是Java提供的不可變的、任意精度的有符號十進制數。如果想看更多關于BigDecimal的介紹,大家可以自行去查看JDK的文檔。
BigDecimal提供了一系列的構造函數,主用于將double , string等轉化成BigDecimal對象。
習慣上我們在使用浮點數的時候都是直接定義的double , float數據類型,在定義上是沒有問題,但是如果我們直接調用BigDecimal(double val) 方法來轉化,那我們可得先注意一下JDK文檔中關于這個構造的詳細說明了:
直接上中文了,英文好的,可以自己去看原版:
注:
此構造方法的結果有一定的不可預知性。有人可能認為在 Java 中寫入 new BigDecimal(0.1) 所創建的 BigDecimal 正好等于 0.1(非標度值 1,其標度為 1),但是它實際上等于 0.1000000000000000055511151231257827021181583404541015625。這是因為 0.1 無法準確地表示為 double(或者說對于該情況,不能表示為任何有限長度的二進制小數)。這樣,傳入 到構造方法的值不會正好等于 0.1(雖然表面上等于該值)。
BigDecimal(double val) 這個方法是不可預知的,所以我們推薦使用BigDecimal(String val) 。
String的構造函數就是可預知的,new BigDecimal(“.1”)如同期望的那樣精確的等于.1。
接下來我們對 0.05+0.01重新修改一下:
BigDecimal bd1 = new BigDecimal(Double.toString(0.05));BigDecimal bd2 = new BigDecimal(Double.toString(0.01));System.out.println(bd1.add( bd2));我們再來看看運行的結果:
0.06這下就是我們想要的結果了,完成了高精度的一個運算了。
注意:
?現在我們已經知道怎么樣來解決這個問題了,原則上是推薦使用BigDecimal(String val) 構造方法。
我建議,在商業的應用中,涉及到money的浮點運算全都定義成String ,在數據庫中保存也是String ,在需要使用到這個money來作運算的時候,我們再把String轉化成BigDecimal來完成高精度的運算。
????????
試想一下,如果我們要做一個加法運算,需要先將兩個浮點數轉為String,然后夠造成BigDecimal,在其中一個上調用add方法,傳入另一個作為參數,然后把運算的結果(BigDecimal)再轉換為浮點數。你能夠忍受這么煩瑣的過程嗎?
SO, 網上找了一個比較好的一個工具類,封閉了簡單的操作。可以參考一下:
?首發地址:http://www.eoeandroid.com/thread-230579-1-1.html
另外一個地址:http://krislq.com/150?? 嘎嘎!
轉載于:https://www.cnblogs.com/nuliniaoboke/archive/2012/11/21/2780557.html
總結
以上是生活随笔為你收集整理的关于不能够精确的对浮点数进行运算的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [ -~] 所有的可打印字符
- 下一篇: 计算机科学主要领域