一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java DecimalFormat 保留小數位及四舍五入的陷阱介紹

Java DecimalFormat 保留小數位及四舍五入的陷阱介紹

2022-02-16 11:01智鼎在線IT團隊 Java教程

這篇文章主要介紹了Java DecimalFormat 保留小數位及四舍五入的陷阱,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

需求

業務需要導出的Excel的數字內容保留兩位小數,并且四舍五入

代碼實現

百度一圈所抄襲的代碼

?
1
2
DecimalFormat dfScale2 = new DecimalFormat("###.##");
dfScale2.format(1.125D);

發現問題

導出數據很詭異.不是所有數據都是如所想的四舍五入.

經過排查最終發現是RoundingMode的問題,應該使用HALF_UP,

DecimalFormat 默認使用的是HALF_EVEN

?
1
2
3
4
5
DecimalFormat dfScale2 = new DecimalFormat("###.##");
System.out.println("dfScale2.getRoundingMode()=" + dfScale2.getRoundingMode());
//輸出結果
dfScale2.getRoundingMode()=HALF_EVEN
//

RoundingMode.HALF_EVEN

想了解HALF_EVEN,去官網API看了下

HALF_EVEN 被舍位是5(如保留兩位小數的2.115),后面還有非0值進1(如保留兩位小數的2.11500001 格式化為2.12),5后面沒有數字或者都是0時,前面是偶數則舍,是奇數則進1,目標是讓被舍前一位變為偶數.

  • CEILING 向更大的值靠近
  • Rounding mode to round towards positive infinity.
  • DOWN向下取整
  • Rounding mode to round towards zero.
  • FLOOR 向更小的值靠近
  • Rounding mode to round towards negative infinity.
  • HALF_DOWN 五舍六入
  • Rounding mode to round towards “nearest neighbor” unless both neighbors are equidistant, in which case round down.
  • HALF_EVEN
  • Rounding mode to round towards the “nearest neighbor” unless both neighbors are equidistant, in which case, round towards the even neighbor.
  • HALF_UP 四舍五入
  • Rounding mode to round towards “nearest neighbor” unless both neighbors are equidistant, in which case round up.
  • UNNECESSARY 設置這個模式,對于精確值格式化會拋出異常
  • Rounding mode to assert that the requested operation has an exact result, hence no rounding is necessary.
  • UP 向遠離數字0進行進位.
  • Rounding mode to round away from zero.

錯誤的代碼測試RoundingMode.HALF_EVEN

為了更好的理解HALF_EVEN,寫了些測試代碼但是發現自己更迷惘了…搞不清楚到底HALF_EVEN是什么機制進舍…輸出結果的尾數很不規律.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
public class LocalTest {
//定義一個保留兩位小數格式的 DecimalFormat 的變量 dfScale2
 @Test
  public void testDecimalFormat() {
    DecimalFormat dfScale2 = new DecimalFormat("###.##");
    System.out.println("dfScale2.getRoundingMode()=" + dfScale2.getRoundingMode());
    System.out.println("dfScale2.format(1.125D)=" + dfScale2.format(1.125D));
    System.out.println("dfScale2.format(1.135D)=" + dfScale2.format(1.135D));
    System.out.println("dfScale2.format(1.145D)=" + dfScale2.format(1.145D));
    System.out.println("dfScale2.format(1.225D)=" + dfScale2.format(1.225D));
    System.out.println("dfScale2.format(1.235D)=" + dfScale2.format(1.235D));
    System.out.println("dfScale2.format(1.245D)=" + dfScale2.format(1.245D));
    System.out.println();
    System.out.println("dfScale2.format(2.125D)=" + dfScale2.format(2.125D));
    System.out.println("dfScale2.format(2.135D)=" + dfScale2.format(2.135D));
    System.out.println("dfScale2.format(2.145D)=" + dfScale2.format(2.145D));
    System.out.println("dfScale2.format(2.225D)=" + dfScale2.format(2.225D));
    System.out.println("dfScale2.format(2.235D)=" + dfScale2.format(2.235D));
    System.out.println("dfScale2.format(2.245D)=" + dfScale2.format(2.245D));
    System.out.println();
    System.out.println("dfScale2.format(3.125D)=" + dfScale2.format(3.125D));
    System.out.println("dfScale2.format(3.135D)=" + dfScale2.format(3.135D));
    System.out.println("dfScale2.format(3.145D)=" + dfScale2.format(3.145D));
    System.out.println("dfScale2.format(3.225D)=" + dfScale2.format(3.225D));
    System.out.println("dfScale2.format(3.235D)=" + dfScale2.format(3.235D));
    System.out.println("dfScale2.format(3.245D)=" + dfScale2.format(3.245D));
    System.out.println();
    System.out.println("dfScale2.format(4.125D)=" + dfScale2.format(4.125D));
    System.out.println("dfScale2.format(4.135D)=" + dfScale2.format(4.135D));
    System.out.println("dfScale2.format(4.145D)=" + dfScale2.format(4.145D));
    System.out.println("dfScale2.format(4.225D)=" + dfScale2.format(4.225D));
    System.out.println("dfScale2.format(4.235D)=" + dfScale2.format(4.235D));
    System.out.println("dfScale2.format(4.245D)=" + dfScale2.format(4.245D));
  }
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
dfScale2.getRoundingMode()=HALF_EVEN
dfScale2.format(1.125D)=1.12
dfScale2.format(1.135D)=1.14
dfScale2.format(1.145D)=1.15
dfScale2.format(1.225D)=1.23
dfScale2.format(1.235D)=1.24
dfScale2.format(1.245D)=1.25
dfScale2.format(2.125D)=2.12
dfScale2.format(2.135D)=2.13
dfScale2.format(2.145D)=2.15
dfScale2.format(2.225D)=2.23
dfScale2.format(2.235D)=2.23
dfScale2.format(2.245D)=2.25
dfScale2.format(3.125D)=3.12
dfScale2.format(3.135D)=3.13
dfScale2.format(3.145D)=3.15
dfScale2.format(3.225D)=3.23
dfScale2.format(3.235D)=3.23
dfScale2.format(3.245D)=3.25
dfScale2.format(4.125D)=4.12
dfScale2.format(4.135D)=4.13
dfScale2.format(4.145D)=4.14
dfScale2.format(4.225D)=4.22
dfScale2.format(4.235D)=4.24
dfScale2.format(4.245D)=4.25

正確的代碼測試RoundingMode.HALF_EVEN

突然發現自己忽略了一個事情,測試的參數都是用的double類型.想起來double類型不精準.但是僥幸心理以及知識不牢靠以為 3位小數應該影響不大吧.改了下代碼,把參數改為BigDecimal類型

使用BigDecimal時,參數盡量傳入字符串,要比傳入double精準.

?
1
new BigDecimal("1.125")
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void testDecimalFormat() {
  DecimalFormat dfScale2 = new DecimalFormat("###.##");
    dfScale2.setRoundingMode(RoundingMode.HALF_EVEN);
  System.out.println("dfScale2.getRoundingMode()=" + dfScale2.getRoundingMode());
      System.out.println("dfScale2.format(new BigDecimal(\"1.1251\"))=" + dfScale2.format(new BigDecimal("1.1251")));
  System.out.println("dfScale2.format(new BigDecimal(\"1.1351\"))=" + dfScale2.format(new BigDecimal("1.1351")));
  System.out.println("dfScale2.format(new BigDecimal(\"1.1451\"))=" + dfScale2.format(new BigDecimal("1.1451")));
  System.out.println("dfScale2.format(new BigDecimal(\"1.2250\"))=" + dfScale2.format(new BigDecimal("1.2250")));
  System.out.println("dfScale2.format(new BigDecimal(\"1.2350\"))=" + dfScale2.format(new BigDecimal("1.2350")));
  System.out.println("dfScale2.format(new BigDecimal(\"1.2450\"))=" + dfScale2.format(new BigDecimal("1.2450")));
  System.out.println("dfScale2.format(new BigDecimal(\"1.22501\"))=" + dfScale2.format(new BigDecimal("1.22501")));
  System.out.println("dfScale2.format(new BigDecimal(\"1.23505\"))=" + dfScale2.format(new BigDecimal("1.23505")));
  System.out.println("dfScale2.format(new BigDecimal(\"1.24508\"))=" + dfScale2.format(new BigDecimal("1.24508")));
?
1
2
3
4
5
6
7
8
9
10
dfScale2.getRoundingMode()=HALF_EVEN
dfScale2.format(new BigDecimal("1.1251"))=1.13
dfScale2.format(new BigDecimal("1.1351"))=1.14
dfScale2.format(new BigDecimal("1.1451"))=1.15
dfScale2.format(new BigDecimal("1.2250"))=1.22
dfScale2.format(new BigDecimal("1.2350"))=1.24
dfScale2.format(new BigDecimal("1.2450"))=1.24
dfScale2.format(new BigDecimal("1.22501"))=1.23
dfScale2.format(new BigDecimal("1.23505"))=1.24
dfScale2.format(new BigDecimal("1.24508"))=1.25

結論

1、警覺doulbe的不精確所引起RoundingMode結果不穩定的問題,即使是四舍五入的模式,對double類型參數使用也會有不滿足預期的情況.

2、使用數字格式化時,要注意默認RoundingMode模式是否是自己需要的.如果不是記得手動設置下.

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/baixf/article/details/88792219

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 四虎影院的网址 | chinese一bdsmⅹxx| 日本高清中文字幕一区二区三区 | 福利片成人午夜在线 | 日本免费不卡在线一区二区三区 | 精品免费久久久久久成人影院 | 四虎最新永久免费视频 | 色综合久久中文字幕网 | 国产日韩欧美色视频色在线观看 | 91会员 | 91精品国产91久久久久久麻豆 | 亚洲成年人在线观看 | 美女gif跪趴式抽搐动态图 | 忘忧草在线社区WWW日本-韩国 | 亚洲成在人线久久综合 | 午夜福利08550 | 精品国语对白精品自拍视 | tolove第一季动画在线看 | 俄罗斯烧性春三级k8播放 | 亚洲精品乱码久久久久久蜜桃 | 手机看片自拍自自拍日韩免费 | 狠狠干狠狠插 | 小早川怜子在线播放精品 | www.四虎影| 黄a在线观看 | 忘忧草在线社区WWW日本-韩国 | 亚洲高清中文字幕 | 国产成人咱精品视频免费网站 | 国内体内she精视频免费 | 午夜福利试看120秒体验区 | 色婷婷影院在线视频免费播放 | 99re这里都是精品 | 免费观看成年人视频 | 高清一级做a爱免费视 | 青草园网站在线观看 | 处女摘花 | 日本在线看| 毛片网站大全 | 国产午夜成人无码免费看 | m3u8久久国产精品影院 | 好涨好爽乱岳 |