日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 中浮点数---------BigDecimal和double(初探)

發布時間:2025/3/21 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 中浮点数---------BigDecimal和double(初探) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為什么要使用 bigdecimal?

借用《Effactive Java》這本書中的話,floatdouble類型的主要設計目標是為了科學計算和工程計算。他們執行二進制浮點運算,這是為了在廣域數值范圍上提供較為精確的快速近似計算而精心設計的。然而,它們沒有提供完全精確的結果,所以不應該被用于要求精確結果的場合。但是,商業計算往往要求結果精確,這時候BigDecimal就派上大用場啦。

?

BigDecimal簡介

????????BigDecimal 由任意精度的整數非標度值?32 位的整數標度?(scale) 組成。如果為零或正數,則標度是小數點后的位數。如果為負數,則將該數的非標度值乘以 10 的負scale 次冪。因此,BigDecimal表示的數值是(unscaledValue × 10-scale)

?

構造方法

BigDecimal aString = new BigDecimal("1.22");

BigDecimal aDouble = new BigDecimal(1.22);

BigDecimal bDouble = BigDecimal.valueOf(1.22);

System.out.println(aString);

System.out.println(aDouble);

System.out.println(bDouble);

Result:

1.22

1.2199999999999999733546474089962430298328399658203125

1.22

源碼分析:

BigDecimal.valueOf(1.22) 構造方法,其實是調用 構造方法BigDecimal(String val)

?

?

Jdk中有說明:

1、參數類型為double的構造方法的結果有一定的不可預知性。有人可能認為在Java中寫入newBigDecimal(0.1)所創建的BigDecimal正好等于 0.1(非標度值 1,其標度為 1),但是它實際上等于0.1000000000000000055511151231257827021181583404541015625。這是因為0.1無法準確地表示為 double(或者說對于該情況,不能表示為任何有限長度的二進制小數)。這樣,傳入到構造方法的值不會正好等于 0.1(雖然表面上等于該值)。

2、另一方面,String 構造方法是完全可預知的:寫入 newBigDecimal("0.1") 將創建一個 BigDecimal,它正好等于預期的 0.1。因此,比較而言,通常建議優先使用String構造方法。

3、當double必須用作BigDecimal的源時,請注意,此構造方法提供了一個準確轉換;它不提供與以下操作相同的結果:先使用Double.toString(double)方法,然后使用BigDecimal(String)構造方法,將double轉換為String。要獲取該結果,請使用static valueOf(double)方法。

?

?

?

在數據量精度不是很大的情況下,通過decimal輸出正確的結果。(保留三位小數)

BigDecimal aString = new BigDecimal("1.22");

BigDecimal aDouble = new BigDecimal(1.22);

BigDecimal aValue = BigDecimal.valueOf(1.22);

System.out.println(new DecimalFormat("0.000").format(aString));

System.out.println(new DecimalFormat("0.000").format(aDouble));

System.out.println(new DecimalFormat("0.000").format(aValue));

Result

1.220

1.220

1.220

原因分析:DecimalFormat做用了自己的舍余規則

?

?

?

總結

(1)商業計算使用BigDecimal

(2)盡量使用參數類型為String的構造函數。

(3) BigDecimal都是不可變的(immutable)的,在進行每一步運算時,都會產生一個新的對象,所以在做加減乘除運算時千萬要保存操作后的值。

(4)我們往往容易忽略JDK底層的一些實現細節,導致出現錯誤,需要多加注意。

?

?

問題一:BigDecimal的精度問題(StackOverflow上有個家伙問了相關的問題)

?

System.out.println(new BigDecimal(0.1).toString()); // 0.1000000000000000055511151231257827021181583404541015625 System.out.println(new BigDecimal("0.1").toString()); // 0.1 System.out.println(new BigDecimal( Double.toString(0.1000000000000000055511151231257827021181583404541015625)).toString());// 0.1 System.out.println(new BigDecimal(Double.toString(0.1)).toString()); // 0.1

  

分析一下上面代碼的問題(注釋的內容表示此語句的輸出)

第一行:事實上,由于二進制無法精確地表示十進制小數0.1,但是編譯器讀到字符串"0.1"之后,必須把它轉成8個字節的double值,因此,編譯器只能用一個最接近的值來代替0.1了,即0.1000000000000000055511151231257827021181583404541015625。因此,在運行時,傳給BigDecimal構造函數的真正的數值是0.1000000000000000055511151231257827021181583404541015625。 第二行:BigDecimal能夠正確地把字符串轉化成真正精確的浮點數。 第三行:問題在于Double.toString會使用一定的精度來四舍五入double,然后再輸出。會。Double.toString(0.1000000000000000055511151231257827021181583404541015625)輸出的事實上是"0.1",因此生成的BigDecimal表示的數也是0.1。 第四行:基于前面的分析,事實上這一行代碼等價于第三行 結論: 1.如果你希望BigDecimal能夠精確地表示你希望的數值,那么一定要使用字符串來表示小數,并傳遞給BigDecimal的構造函數。 2.如果你使用Double.toString來把double轉化字符串,然后調用BigDecimal(String),這個也是不靠譜的,它不一定按你的想法工作。 3.如果你不是很在乎是否完全精確地表示,并且使用了BigDecimal(double),那么要注意double本身的特例,double的規范本身定義了幾個特殊的double值(Infinite,-Infinite,NaN),不要把這些值傳給BigDecimal,否則會拋出異常。 問題二:把double強制轉化成int,難道不是扔掉小數部分嗎? int x=(int)1023.99999999999999; // x=1024為什么?

原因還是在于二進制無法精確地表示某些十進制小數,因此1023.99999999999999在編譯之后的double值變成了1024。

所以,把double強制轉化成int確實是扔掉小數部分,但是你寫在代碼中的值,并不一定是編譯器生成的真正的double值。 驗證代碼: double d = 1023.99999999999999; int x = (int) d; System.out.println(new BigDecimal(d).toString()); // 1024 System.out.println(Long.toHexString(Double.doubleToRawLongBits(d))); // 4090000000000000 System.out.println(x); // 1024

前面提過BigDecimal可以精確地把double表示出來還記得吧。

我們也可以直接打印出d的二進制形式,根據IEEE 754的規定,我們可以算出0x4090000000000000=(1024)。 問題二:BigDecimal如何比較大小? public static void main(String[] args) {BigDecimal a = BigDecimal.valueOf(1.01);BigDecimal b = BigDecimal.valueOf(1.00000001);if (a.compareTo(b) == 0) {System.out.println("a==b");} else if (a.compareTo(b) == 1) {System.out.println("a>b");} else if (a.compareTo(b) == -1) {System.out.println("a<b");}}

?

?

?

參考:

http://www.cnblogs.com/mingforyou/p/3344489.html

http://stackoverflow.com/questions/8073912/why-do-we-need-to-convert-the-double-into-a-string-before-we-can-convert-it-int

http://www.cnblogs.com/linjiqin/p/3413894.html

轉載于:https://www.cnblogs.com/chihirotan/p/5857827.html

總結

以上是生活随笔為你收集整理的Java 中浮点数---------BigDecimal和double(初探)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美色视频一区二区三区 | 色就是色综合 | 亚洲高清网 | 原神女裸体看个够无遮挡 | 欧美丰满熟妇bbbbbb百度 | 国产9区 | 男男做爰猛烈啪啪高 | 99xav| 熟女少妇a性色生活片毛片 亚洲伊人成人网 | 亚洲欧美日韩精品一区 | 国产九九热 | 亚洲精品视频免费看 | 糖心vlog精品一区二区 | 69er小视频 | 毛片a片免费观看 | 欧美成人乱码一区二区三区 | 久久久午夜精品 | 韩国一区在线 | 欧美体内谢she精2性欧美 | 久久99精品久久久久婷婷 | 成人做受视频试看60秒 | 91精品国产闺蜜国产在线闺蜜 | 国产精品9999 | 懂色aⅴ国产一区二区三区 亚洲欧美国产另类 | 男人午夜剧场 | 免费久久视频 | 91免费在线视频观看 | 黄免费在线观看 | 变态另类丨国产精品 | 香蕉黄视频 | 丁香久久婷婷 | 日韩影视一区二区三区 | 777欧美| 日本黄色xxxxx | 在线播放无码后入内射少妇 | 久久成人高清 | 污视频网站在线观看 | 五月花成人网 | 免费成人深夜夜行网站视频 | 日本一区二区在线免费 | 公侵犯人妻一区二区三区 | 色爱AV综合网国产精品 | 亚洲视频手机在线观看 | 视频在线观看电影完整版高清免费 | 日本a在线播放 | 一级黄色录像免费观看 | 免费裸体视频网站 | 91视频最新地址 | 亚洲爽妇网 | 超碰操| 91porny丨首页入口在线 | 日本午夜一区二区三区 | 日日干夜夜艹 | aa免费视频| 欧美成人手机视频 | 99这里有精品视频 | 欧美精品一区二区视频 | 中文日韩在线 | 欧美中文字幕在线 | 免费黄色美女网站 | 久久天堂电影 | 男人插女人网站 | 国产精品一国产精品 | 看污片网站| 蜜桃视频日韩 | 国产欧美日韩在线观看 | 欧美一区二区三区免费在线观看 | 欧美一区二区三区的 | 亚洲精品字幕在线 | av在线第一页 | 黄色免费一级片 | 虫族全黄h全肉污文 | 骚虎视频在线观看 | 少妇激情偷人爽爽91嫩草 | 四虎影院www| 欧美暧暧视频 | 国产91丝袜在线观看 | 久久成人久久爱 | 一级片免费在线 | 狠狠干一区二区 | 在线观看国产黄色 | 夜夜高潮夜夜爽国产伦精品 | 我爱52av | 亚洲天堂av在线免费观看 | 亚洲综合网av | 黑人3p波多野结衣在线观看 | 欧美色人阁 | 青娱乐在线播放 | 综合网伊人 | 青娱乐久久 | 国产精品一区二区三区在线播放 | 日韩精品免费一区二区 | 日韩国产激情 | 欧美一级免费 | 狠狠a| 奇米影视第四色首页 | 夜夜高潮夜夜爽国产伦精品 | 主人性调教le百合sm | 国语毛片 |