Java數值加減乘除結果都是對的么?丨【奔跑吧!JAVA】

      網友投稿 1408 2022-05-30

      計算機程序內部都是二進制表示的,日常的編程實戰中,除了處理字符串外,大部分情況下,都在處理數值的計算,如計算多個值的和或平均值。在Java語言體系中,關于數值的類型有int,float,double,long等。

      Java中數值的加減乘除結果都是對的么?丨【奔跑吧!JAVA】

      對于有小數的數值,開發人員首先想到的是可以用float或者double表示。比如求1.0和0.42兩個值的差,那么心算可得0.58,但是如果用Java來實際計算一下,那么其結果可能和我們預期的是不一樣的。

      下面結合特殊場景,來給出Java常見的數值加減乘除運算示例,看看結果都是對的么?具體的示例代碼如下:

      package com.jyd; //Java 數值計算精度問題探討示例 public class NumDemo { public static void main(String[] args) { int a = 10; int c0 = a / 3 ; System.out.println(c0);//3,只保留整數 //float和double大部分情況精確的,但有時會計算錯誤 // 在商業計算上(如金融、銀行,財務),不建議使用。 float b = 0.1f; float c2 = b / 3.0f;//0.033333335 System.out.println(c2); float b2 = 20019999; System.out.println(b2); //2.002E7 double d = 45.9D; double c3 = d / 3.0D ; System.out.println(c3);//15.299999999999999 (not 15.3) double e = 2001299.32D; double e2 = 0.11D; System.out.println(e + e2); //2001299.4300000002 System.out.println(1.0 - 0.42);//0.5800000000000001 System.out.println(4.015 * 100);//401.49999999999994 System.out.println(0.01 + 0.05);//0.060000000000000005 } }

      上述示例代碼中,int類型的數值10,/ 除以3,實際返回的是int類型,即3,只保留整數部分。這個計算結果只要我們知道,一般都可以理解。Java中的浮點類型(如float和double)采用?IEEE 754?標準。float類型的值0.1除以3.0時,返回的還是float類型的值,按照數學角度來說,應該返回0.3333...(循環),但是Java程序返回0.033333335。float類型長度為32位,其中用?1?位表示數字的符號,用?8?位表示指數,用?23?位表示小數部分。感覺這個長度有的長,但是實際使用起來精度還是不夠。即使是64位的double也是如此。

      示例中,20019999這個float類型的值,輸出后卻是2.002E7,即20020000,真是奇乎怪哉!,如果這個是銀行賬戶的金額,1個賬戶多1元,那么幾億個戶頭則多出了幾個億的金額,足見這個計算精度的問題是在特殊場景下,是一個不可接受的方案。 其他的示例涉及到加法、減法、乘法,也同樣會出現計算錯誤的問題。

      按照官網的說法,float和double一般用于工程計算,而不能應用商業計算,如銀行,財務等。那么商業計算上,該如何解決此問題呢?此時需要用到一個特殊的類型,為BigDecimal。此類型是一個精確的類型,下面給出示例:

      package com.jyd; import java.math.BigDecimal; import java.math.MathContext; //Java 數值計算精度問題探討示例 public class BigNumDemo { public static void main(String[] args) { BigDecimal b = new BigDecimal("0.1"); BigDecimal b1 = new BigDecimal("3.0"); BigDecimal c2 = b.divide(b1,10,BigDecimal.ROUND_DOWN) ;//0.0333333333 System.out.println(c2); BigDecimal b2 = new BigDecimal(""+20019999); System.out.println(b2); //20019999 BigDecimal d = new BigDecimal("45.9"); BigDecimal d2 = new BigDecimal("3.0"); BigDecimal c3 = d.divide(d2,10,BigDecimal.ROUND_CEILING) ; System.out.println(c3);//15.3000000000 BigDecimal e = new BigDecimal("2001299.32"); BigDecimal e2 = new BigDecimal("0.11"); System.out.println(e.add(e2)); //2001299.43 BigDecimal e3 = new BigDecimal("1.0"); BigDecimal e4 = new BigDecimal("0.42"); System.out.println(e3.subtract(e4));//0.58 BigDecimal e5 = new BigDecimal("4.015"); BigDecimal e6 = new BigDecimal("100"); System.out.println(e5.multiply(e6, MathContext.UNLIMITED));//401.500 BigDecimal e7 = new BigDecimal("0.01"); BigDecimal e8 = new BigDecimal("0.05"); System.out.println(e7.add(e8));//0.06 BigDecimal e9 = new BigDecimal("999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"); System.out.println(e9.add(e3));//1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 } }

      BigDecimal有多種構造函數,常用的有2種。建議使用String構造方式,不建議使用double構造方式,可能會出現精度丟失問題。通過上述示例可以看出,商業計算應該使用 BigDecimal類型來完成,雖然在加減乘除這塊使用起來有點不夠簡便,但是仍然比較容易理解。且操作字符串,也更容易操作。在乘除計算中,強制需要制定額外的參數,比如明確小數個數,四舍五入的模式等。

      最后,Java編程的細節還有很多,比如不同精度的數值的賦值和轉換問題,float和double為什么會導致數據精度的丟失等,可以參考官網文檔或其他資料。這里不再贅述。

      【奔跑吧!JAVA】有獎征文火熱進行中:

      https://bbs.huaweicloud.com/blogs/265241

      Java

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:python字典實例(部分)
      下一篇:通過 Maven 編譯打包 Java + Scala 混合項目
      相關文章
      亚洲欧洲免费无码| 亚洲人成电影福利在线播放| 久久精品国产亚洲77777| 国产亚洲av片在线观看16女人| 亚洲国产午夜福利在线播放| 日韩精品成人亚洲专区| 国产精品亚洲专区在线播放| 亚洲国产成人精品无码区花野真一| 亚洲色大成网站www| 亚洲精品无码久久久久A片苍井空 亚洲精品无码久久久久YW | 色噜噜综合亚洲av中文无码| 亚洲精品免费在线观看| 久久夜色精品国产噜噜噜亚洲AV | 亚洲AV无码专区国产乱码4SE| 九月丁香婷婷亚洲综合色| 亚洲国产精品无码久久一区二区 | 亚洲AV无码一区二区乱子伦 | 亚洲av成人片在线观看| 朝桐光亚洲专区在线中文字幕| 朝桐光亚洲专区在线中文字幕| 国产精品亚洲一区二区在线观看| 亚洲成a人无码亚洲成av无码 | 99久久婷婷国产综合亚洲| 亚洲综合一区无码精品| 亚洲youwu永久无码精品| 午夜亚洲av永久无码精品| 亚洲日本一区二区一本一道| 中文字幕精品亚洲无线码二区| 亚洲桃色AV无码| 亚洲av日韩av高潮潮喷无码| 亚洲色大成网站WWW久久九九| 亚洲天堂在线视频| 亚洲精品无码久久千人斩| 亚洲人成在线观看| 亚洲丰满熟女一区二区v| 亚洲国产aⅴ成人精品无吗| 亚洲国产精品成人网址天堂 | 亚洲jizzjizz在线播放久| 国产亚洲精品无码专区| AV在线亚洲男人的天堂| 国产国拍亚洲精品福利 |