自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

又踩坑了!BigDecimal使用的五個坑!

大數據 數據分析
由于計算機的資源是有限的,所以是沒辦法用二進制精確的表示 0.1,只能用「近似值」來表示,就是在有限的精度情況下,最大化接近 0.1 的二進制數,于是就會造成精度缺失的情況。

前言

大家好,我是田螺。

在日常開發(fā)中,BigDecimal類被廣泛用于精確的數值、金額的計算。但是在使用BigDecimal的過程中,存在以下這幾個坑,大家要注意一下哈~~

1.浮點數初始化的坑

反例:

BigDecimal problematic = new BigDecimal(0.1);
System.out.println("Problematic: " + problematic.toString()); 
//輸出 Problematic: 0.1000000000000000055511151231257827021181583404541015625

可以發(fā)現,直接使用new BigDecimal(double)構造方法可能會得到一個看起來相當奇怪的結果。這是因為double本身的精度問題會被帶入BigDecimal中。為了避免這個問題,推薦使用String參數的構造方法或者使用BigDecimal.valueOf方法,例如new BigDecimal("0.1"),這樣可以確保BigDecimal的精度。

由于計算機的資源是有限的,所以是沒辦法用二進制精確的表示 0.1,只能用「近似值」來表示,就是在有限的精度情況下,最大化接近 0.1 的二進制數,于是就會造成精度缺失的情況。

正例:

BigDecimal problematic1 =  BigDecimal.valueOf(0.1);
System.out.println("Problematic: " + problematic1.toString());

BigDecimal problematic2 =  new BigDecimal("0.1");
System.out.println("Problematic: " + problematic2.toString());
//輸出
Problematic: 0.1
Problematic: 0.1

2. 比較數值時使用compareTo()方法而非equals()

BigDecimal bd1 = new BigDecimal("0.10");
BigDecimal bd2 = new BigDecimal("0.1");
System.out.println(bd1.equals(bd2)); // 輸出: false
System.out.println(bd1.compareTo(bd2) == 0); // 輸出: true

BigDecimal的equals方法不僅比較數值,還會比較對象的scale(小數點后的位數),如果只想比較數值,而不考慮scale,應該使用compareTo方法。

圖片圖片

3.做除法時,未指定精度可能異常

BigDecimal dividend = new BigDecimal("10");
BigDecimal divisor = new BigDecimal("3");
BigDecimal result = dividend.divide(divisor); // 未指定精度和舍入模式
System.out.println(result);
//輸出
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
 at java.math.BigDecimal.divide(BigDecimal.java:1693)
 at com.example.demo.controller.Test.main(Test.java:26)

除法操作將10除以3,結果是無限循環(huán)小數3.3333...,但由于未指定精度和舍入模式,會拋出ArithmeticException異常。

官方有給出解釋:

"If the quotient has a nonterminating decimal expansion and the operation is specified to return an exact result, an ArithmeticException is thrown. Otherwise, the exact result of the division is returned, as done for other operations."

要使用BigDecimal時,要記得指定精度,避免因為精度問題帶來的損失。

4. BigDecimal轉String,科學計數法展示問題

System.out.println( new BigDecimal("0.0000000000001").toString());
BigDecimal bigDecimal = new BigDecimal("1E+12");
System.out.println(bigDecimal.toString());
//輸出 1E-13
//輸出 1E+12

這是因為 toString() 某些場景下使用科學計數法展示。如果不想用任何計數法,可以使用 toPlainString()

System.out.println( new BigDecimal("0.0000000000001").toPlainString());
BigDecimal bigDecimal = new BigDecimal("1E+12");
System.out.println(bigDecimal.toPlainString());
//輸出 
0.0000000000001
1000000000000

5. 注意使用setScale方法設置精度

BigDecimal number = new BigDecimal("123.4567");
BigDecimal roundedNumber = number.setScale(2, RoundingMode.HALF_UP);
//輸出
123.46

因為BigDecimal的精度是無限的,因此一般在計算的時候,要注意設置精度幾位。

并且,RoundingMode.HALF_UP 是一種舍入模式,用于四舍五入,即當數字的一部分被舍去時,如果剩余部分大于或等于0.5,則向上舍入。除了HALF_UP之外,還有幾個常用的舍入模式:

  • UP:遠離零方向舍入的舍入模式。總是在非零舍棄部分之前增加數字。
  • DOWN:接近零方向舍入的舍入模式??偸窃诜橇闵釛壊糠种皽p少數字。
  • CEILING:接近正無窮大的方向舍入的舍入模式。如果BigDecimal是正的,則舍入行為與UP相同;如果是負的,則舍入行為與DOWN相同。
  • FLOOR:接近負無窮大的方向舍入的舍入模式。如果BigDecimal是正的,則舍入行為與DOWN相同;如果是負的,則舍入行為與UP相同。
  • HALF_DOWN:向“最近鄰居”舍入,除非兩邊距離相等,此時向下舍入。
  • HALF_EVEN:向“最近鄰居”舍入,除非兩邊距離相等,此時向偶數舍入。這種模式也稱為“銀行家舍入法”,因為它減少了累計錯誤。

還有一個點,就是:使用setScale方法實際上會產生一個全新的BigDecimal實例,而不會更改原有對象。所以,當你用setScale調整了數字精度后,別忘了把新生成的對象賦值回原來的變量。

責任編輯:武曉燕 來源: 撿田螺的小男孩
相關推薦

2022-11-18 07:34:12

Docker項目目錄

2024-02-04 08:26:38

線程池參數內存

2023-06-30 08:10:14

JavaBigDecimal

2023-03-06 07:50:19

內存回收Go

2024-11-20 18:16:39

MyBatis批量操作數據庫

2024-03-11 18:17:18

Python字符串分隔符

2022-12-23 08:37:16

BigDecimaljava

2025-04-29 10:17:42

2021-09-09 18:12:22

內存分段式網絡

2024-05-06 00:00:00

緩存高并發(fā)數據

2017-07-17 15:46:20

Oracle并行機制

2024-11-26 08:20:53

程序數據歸檔庫

2020-09-29 07:57:48

設置HttpClientContent-Typ

2022-02-28 08:55:31

數據庫MySQL索引

2023-02-20 08:11:04

2015-03-24 16:29:55

默認線程池java

2023-01-18 23:20:25

編程開發(fā)

2020-09-15 08:46:26

Kubernetes探針服務端

2020-09-06 10:02:32

項目管理戰(zhàn)略目標CIO

2018-12-18 14:13:30

SDKAndroid開發(fā)
點贊
收藏

51CTO技術棧公眾號