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

Java中的BigDecimal,你真的會(huì)用嗎?

開發(fā) 后端
雙精度浮點(diǎn)型變量double可以處理16位有效數(shù),但在實(shí)際應(yīng)用中,可能需要對更大或者更小的數(shù)進(jìn)行運(yùn)算和處理。

一、BigDecimal概述

Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數(shù)進(jìn)行精確的運(yùn)算。雙精度浮點(diǎn)型變量double可以處理16位有效數(shù),但在實(shí)際應(yīng)用中,可能需要對更大或者更小的數(shù)進(jìn)行運(yùn)算和處理。

一般情況下,對于那些不需要準(zhǔn)確計(jì)算精度的數(shù)字,我們可以直接使用Float和Double處理,但是Double.valueOf(String) 和Float.valueOf(String)會(huì)丟失精度。所以開發(fā)中,如果我們需要精確計(jì)算的結(jié)果,則必須使用BigDecimal類來操作。

BigDecimal所創(chuàng)建的是對象,故我們不能使用傳統(tǒng)的+、-、*、/等算術(shù)運(yùn)算符直接對其對象進(jìn)行數(shù)學(xué)運(yùn)算,而必須調(diào)用其相對應(yīng)的方法。方法中的參數(shù)也必須是BigDecimal的對象。構(gòu)造器是類的特殊方法,專門用來創(chuàng)建對象,特別是帶有參數(shù)的對象。

二、BigDecimal常用構(gòu)造函數(shù)

2.1、常用構(gòu)造函數(shù)

  •  BigDecimal(int)

創(chuàng)建一個(gè)具有參數(shù)所指定整數(shù)值的對象

  •  BigDecimal(double)

創(chuàng)建一個(gè)具有參數(shù)所指定雙精度值的對象

  •  BigDecimal(long)

創(chuàng)建一個(gè)具有參數(shù)所指定長整數(shù)值的對象

  •     BigDecimal(String)

創(chuàng)建一個(gè)具有參數(shù)所指定以字符串表示的數(shù)值的對象

2.2、使用問題分析

使用示例: 

  1. BigDecimal a =new BigDecimal(0.1);  
  2. System.out.println("a values is:"+a);  
  3. System.out.println("=====================");  
  4. BigDecimal b =new BigDecimal("0.1");  
  5. System.out.println("b values is:"+b); 

結(jié)果示例: 

  1. a values is:0.1000000000000000055511151231257827021181583404541015625  
  2. =====================  
  3. b values is:0.1 

原因分析:

1)參數(shù)類型為double的構(gòu)造方法的結(jié)果有一定的不可預(yù)知性。有人可能認(rèn)為在Java中寫入newBigDecimal(0.1)所創(chuàng)建的BigDecimal正好等于 0.1(非標(biāo)度值 1,其標(biāo)度為 1),但是它實(shí)際上等于0.1000000000000000055511151231257827021181583404541015625。這是因?yàn)?.1無法準(zhǔn)確地表示為 double(或者說對于該情況,不能表示為任何有限長度的二進(jìn)制小數(shù))。這樣,傳入到構(gòu)造方法的值不會(huì)正好等于 0.1(雖然表面上等于該值)。

2)String 構(gòu)造方法是完全可預(yù)知的:寫入 newBigDecimal(“0.1”) 將創(chuàng)建一個(gè) BigDecimal,它正好等于預(yù)期的 0.1。因此,比較而言, 通常建議優(yōu)先使用String構(gòu)造方法。

3)當(dāng)double必須用作BigDecimal的源時(shí),請注意,此構(gòu)造方法提供了一個(gè)準(zhǔn)確轉(zhuǎn)換;它不提供與以下操作相同的結(jié)果:先使用Double.toString(double)方法,然后使用BigDecimal(String)構(gòu)造方法,將double轉(zhuǎn)換為String。要獲取該結(jié)果,請使用static valueOf(double)方法。Java知音公眾號內(nèi)回復(fù)“面試題聚合”,送你一份面試題寶典

三、BigDecimal常用方法詳解

3.1、常用方法

  •  add(BigDecimal)

BigDecimal對象中的值相加,返回BigDecimal對象

  •  subtract(BigDecimal)

BigDecimal對象中的值相減,返回BigDecimal對象

  •  multiply(BigDecimal)

BigDecimal對象中的值相乘,返回BigDecimal對象

  •  divide(BigDecimal)

BigDecimal對象中的值相除,返回BigDecimal對象

  •  toString()

將BigDecimal對象中的值轉(zhuǎn)換成字符串

  •  doubleValue()

將BigDecimal對象中的值轉(zhuǎn)換成雙精度數(shù)

  •  floatValue()

將BigDecimal對象中的值轉(zhuǎn)換成單精度數(shù)

  •  longValue()

將BigDecimal對象中的值轉(zhuǎn)換成長整數(shù)

  •  intValue()

將BigDecimal對象中的值轉(zhuǎn)換成整數(shù)

3.2、BigDecimal大小比較

java中對BigDecimal比較大小一般用的是bigdemical的compareTo方法 

  1. int a = bigdemical.compareTo(bigdemical2) 

返回結(jié)果分析: 

  1. a = -1,表示bigdemical小于bigdemical2;  
  2. a = 0,表示bigdemical等于bigdemical2;  
  3. a = 1,表示bigdemical大于bigdemical2; 

舉例:a大于等于b 

  1. new bigdemica(a).compareTo(new bigdemical(b)) >= 0 

四、BigDecimal格式化

由于NumberFormat類的format()方法可以使用BigDecimal對象作為其參數(shù),可以利用BigDecimal對超出16位有效數(shù)字的貨幣值,百分值,以及一般數(shù)值進(jìn)行格式化控制。

以利用BigDecimal對貨幣和百分比格式化為例。首先,創(chuàng)建BigDecimal對象,進(jìn)行BigDecimal的算術(shù)運(yùn)算后,分別建立對貨幣和百分比格式化的引用,最后利用BigDecimal對象作為format()方法的參數(shù),輸出其格式化的貨幣值和百分比。 

  1. NumberFormat currency = NumberFormat.getCurrencyInstance(); //建立貨幣格式化引用   
  2. NumberFormat percent = NumberFormat.getPercentInstance();  //建立百分比格式化引用   
  3. percent.setMaximumFractionDigits(3); //百分比小數(shù)點(diǎn)最多3位   
  4. BigDecimal loanAmount = new BigDecimal("15000.48"); //貸款金額  
  5. BigDecimal interestRate = new BigDecimal("0.008"); //利率     
  6. BigDecimal interest = loanAmount.multiply(interestRate); //相乘  
  7. System.out.println("貸款金額:\t" + currency.format(loanAmount));   
  8. System.out.println("利率:\t" + percent.format(interestRate));   
  9. System.out.println("利息:\t" + currency.format(interest));  

結(jié)果:

  1. 貸款金額: ¥15,000.48 利率: 0.8% 利息: ¥120.00 

BigDecimal格式化保留2為小數(shù),不足則補(bǔ)0: 

  1. public class NumberFormat {  
  2.     public static void main(String[] s){  
  3.         System.out.println(formatToNumber(new BigDecimal("3.435")));  
  4.         System.out.println(formatToNumber(new BigDecimal(0)));  
  5.         System.out.println(formatToNumber(new BigDecimal("0.00")));  
  6.         System.out.println(formatToNumber(new BigDecimal("0.001")));  
  7.         System.out.println(formatToNumber(new BigDecimal("0.006")));  
  8.         System.out.println(formatToNumber(new BigDecimal("0.206")));  
  9.     }  
  10.     /**  
  11.      * @desc 1.0~1之間的BigDecimal小數(shù),格式化后失去前面的0,則前面直接加上0。  
  12.      * 2.傳入的參數(shù)等于0,則直接返回字符串"0.00"  
  13.      * 3.大于1的小數(shù),直接格式化返回字符串  
  14.      * @param obj傳入的小數(shù)  
  15.      * @return  
  16.      */  
  17.     public static String formatToNumber(BigDecimal obj) {  
  18.         DecimalFormat df = new DecimalFormat("#.00");  
  19.         if(obj.compareTo(BigDecimal.ZERO)==0) {  
  20.             return "0.00";  
  21.         }else if(obj.compareTo(BigDecimal.ZERO)>0&&obj.compareTo(new BigDecimal(1))<0){  
  22.             return "0"+df.format(obj).toString();  
  23.         }else {  
  24.             return df.format(obj).toString();  
  25.         }  
  26.     }  

結(jié)果為: 

  1. 3.44  
  2. 0.00  
  3. 0.00  
  4. 0.00  
  5. 0.01  
  6. 0.21 

五、BigDecimal常見異常

5.1、除法的時(shí)候出現(xiàn)異常

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result

原因分析:

通過BigDecimal的divide方法進(jìn)行除法時(shí)當(dāng)不整除,出現(xiàn)無限循環(huán)小數(shù)時(shí),就會(huì)拋異常:java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

解決方法:

 divide方法設(shè)置精確的小數(shù)點(diǎn),如:divide(xxxxx,2)

六、BigDecimal總結(jié)

6.1、總結(jié)

在需要精確的小數(shù)計(jì)算時(shí)再使用BigDecimal,BigDecimal的性能比double和float差,在處理龐大,復(fù)雜的運(yùn)算時(shí)尤為明顯。故一般精度的計(jì)算沒必要使用BigDecimal。

盡量使用參數(shù)類型為String的構(gòu)造函數(shù)。

BigDecimal都是不可變的(immutable)的, 在進(jìn)行每一次四則運(yùn)算時(shí),都會(huì)產(chǎn)生一個(gè)新的對象 ,所以在做加減乘除運(yùn)算時(shí)要記得要保存操作后的值。

6.2、工具類推薦 

  1. package com.vivo.ars.util;  
  2. import java.math.BigDecimal;  
  3. /**  
  4.  * 用于高精確處理常用的數(shù)學(xué)運(yùn)算  
  5.  */  
  6. public class ArithmeticUtils {  
  7.     //默認(rèn)除法運(yùn)算精度  
  8.     private static final int DEF_DIV_SCALE = 10 
  9.     /**  
  10.      * 提供精確的加法運(yùn)算  
  11.      *  
  12.      * @param v1 被加數(shù)  
  13.      * @param v2 加數(shù)  
  14.      * @return 兩個(gè)參數(shù)的和  
  15.      */  
  16.     public static double add(double v1, double v2) {  
  17.         BigDecimal b1 = new BigDecimal(Double.toString(v1));  
  18.         BigDecimal b2 = new BigDecimal(Double.toString(v2));  
  19.         return b1.add(b2).doubleValue();  
  20.     }  
  21.     /**  
  22.      * 提供精確的加法運(yùn)算  
  23.      *  
  24.      * @param v1 被加數(shù)  
  25.      * @param v2 加數(shù)  
  26.      * @return 兩個(gè)參數(shù)的和  
  27.      */  
  28.     public static BigDecimal add(String v1, String v2) {  
  29.         BigDecimal b1 = new BigDecimal(v1);  
  30.         BigDecimal b2 = new BigDecimal(v2);  
  31.         return b1.add(b2); 
  32.      } 
  33.     /**  
  34.      * 提供精確的加法運(yùn)算  
  35.      *  
  36.      * @param v1    被加數(shù)  
  37.      * @param v2    加數(shù)  
  38.      * @param scale 保留scale 位小數(shù)  
  39.      * @return 兩個(gè)參數(shù)的和  
  40.      */  
  41.     public static String add(String v1, String v2, int scale) {  
  42.         if (scale < 0) {  
  43.             throw new IllegalArgumentException(  
  44.                     "The scale must be a positive integer or zero");  
  45.         }  
  46.         BigDecimal b1 = new BigDecimal(v1);  
  47.         BigDecimal b2 = new BigDecimal(v2);  
  48.         return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();  
  49.     }  
  50.     /**  
  51.      * 提供精確的減法運(yùn)算  
  52.      *  
  53.      * @param v1 被減數(shù)  
  54.      * @param v2 減數(shù)  
  55.      * @return 兩個(gè)參數(shù)的差  
  56.      */ 
  57.      public static double sub(double v1, double v2) {  
  58.         BigDecimal b1 = new BigDecimal(Double.toString(v1));  
  59.         BigDecimal b2 = new BigDecimal(Double.toString(v2));  
  60.         return b1.subtract(b2).doubleValue();  
  61.     }  
  62.     /**  
  63.      * 提供精確的減法運(yùn)算。  
  64.      *  
  65.      * @param v1 被減數(shù)  
  66.      * @param v2 減數(shù)  
  67.      * @return 兩個(gè)參數(shù)的差  
  68.      */  
  69.     public static BigDecimal sub(String v1, String v2) {  
  70.         BigDecimal b1 = new BigDecimal(v1);  
  71.         BigDecimal b2 = new BigDecimal(v2); 
  72.          return b1.subtract(b2);  
  73.     }  
  74.     /**  
  75.      * 提供精確的減法運(yùn)算  
  76.      * 
  77.      * @param v1    被減數(shù)  
  78.      * @param v2    減數(shù)  
  79.      * @param scale 保留scale 位小數(shù)  
  80.      * @return 兩個(gè)參數(shù)的差  
  81.      */  
  82.     public static String sub(String v1, String v2, int scale) {  
  83.         if (scale < 0) {  
  84.             throw new IllegalArgumentException(  
  85.                     "The scale must be a positive integer or zero");  
  86.         }  
  87.         BigDecimal b1 = new BigDecimal(v1);  
  88.         BigDecimal b2 = new BigDecimal(v2);  
  89.         return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();  
  90.     }  
  91.     /**  
  92.      * 提供精確的乘法運(yùn)算  
  93.      *  
  94.      * @param v1 被乘數(shù)  
  95.      * @param v2 乘數(shù)  
  96.      * @return 兩個(gè)參數(shù)的積  
  97.      */  
  98.     public static double mul(double v1, double v2) {  
  99.         BigDecimal b1 = new BigDecimal(Double.toString(v1));  
  100.         BigDecimal b2 = new BigDecimal(Double.toString(v2));  
  101.         return b1.multiply(b2).doubleValue();  
  102.     }  
  103.     /**  
  104.      * 提供精確的乘法運(yùn)算  
  105.      *  
  106.      * @param v1 被乘數(shù)  
  107.      * @param v2 乘數(shù)  
  108.      * @return 兩個(gè)參數(shù)的積  
  109.      */  
  110.     public static BigDecimal mul(String v1, String v2) {  
  111.         BigDecimal b1 = new BigDecimal(v1);  
  112.         BigDecimal b2 = new BigDecimal(v2);  
  113.         return b1.multiply(b2);  
  114.     }  
  115.     /**  
  116.      * 提供精確的乘法運(yùn)算  
  117.      *  
  118.      * @param v1    被乘數(shù)  
  119.      * @param v2    乘數(shù)  
  120.      * @param scale 保留scale 位小數(shù)  
  121.      * @return 兩個(gè)參數(shù)的積  
  122.      */  
  123.     public static double mul(double v1, double v2, int scale) {  
  124.         BigDecimal b1 = new BigDecimal(Double.toString(v1));  
  125.         BigDecimal b2 = new BigDecimal(Double.toString(v2));  
  126.         return round(b1.multiply(b2).doubleValue(), scale);  
  127.     }  
  128.     /**  
  129.      * 提供精確的乘法運(yùn)算  
  130.      *  
  131.      * @param v1    被乘數(shù)  
  132.      * @param v2    乘數(shù)  
  133.      * @param scale 保留scale 位小數(shù)  
  134.      * @return 兩個(gè)參數(shù)的積  
  135.      */  
  136.     public static String mul(String v1, String v2, int scale) {  
  137.         if (scale < 0) {  
  138.             throw new IllegalArgumentException(  
  139.                     "The scale must be a positive integer or zero");  
  140.         }  
  141.         BigDecimal b1 = new BigDecimal(v1);  
  142.         BigDecimal b2 = new BigDecimal(v2);  
  143.         return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();  
  144.     }  
  145.     /**  
  146.      * 提供(相對)精確的除法運(yùn)算,當(dāng)發(fā)生除不盡的情況時(shí),精確到  
  147.      * 小數(shù)點(diǎn)以后10位,以后的數(shù)字四舍五入 
  148.      *  
  149.      * @param v1 被除數(shù)  
  150.      * @param v2 除數(shù)  
  151.      * @return 兩個(gè)參數(shù)的商  
  152.      */ 
  153.     public static double div(double v1, double v2) {  
  154.         return div(v1, v2, DEF_DIV_SCALE);  
  155.     }  
  156.     /**  
  157.      * 提供(相對)精確的除法運(yùn)算。當(dāng)發(fā)生除不盡的情況時(shí),由scale參數(shù)指  
  158.      * 定精度,以后的數(shù)字四舍五入 
  159.      *  
  160.      * @param v1    被除數(shù)  
  161.      * @param v2    除數(shù)  
  162.      * @param scale 表示表示需要精確到小數(shù)點(diǎn)以后幾位。  
  163.      * @return 兩個(gè)參數(shù)的商  
  164.      */  
  165.     public static double div(double v1, double v2, int scale) {  
  166.         if (scale < 0) {  
  167.             throw new IllegalArgumentException("The scale must be a positive integer or zero");  
  168.         }  
  169.         BigDecimal b1 = new BigDecimal(Double.toString(v1));  
  170.         BigDecimal b2 = new BigDecimal(Double.toString(v2));  
  171.         return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();  
  172.     }  
  173.     /**  
  174.      * 提供(相對)精確的除法運(yùn)算。當(dāng)發(fā)生除不盡的情況時(shí),由scale參數(shù)指  
  175.      * 定精度,以后的數(shù)字四舍五入  
  176.      *  
  177.      * @param v1    被除數(shù)  
  178.      * @param v2    除數(shù)  
  179.      * @param scale 表示需要精確到小數(shù)點(diǎn)以后幾位  
  180.      * @return 兩個(gè)參數(shù)的商  
  181.      */  
  182.     public static String div(String v1, String v2, int scale) {  
  183.         if (scale < 0) {  
  184.             throw new IllegalArgumentException("The scale must be a positive integer or zero");  
  185.         }  
  186.         BigDecimal b1 = new BigDecimal(v1); 
  187.         BigDecimal b2 = new BigDecimal(v1);  
  188.         return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();  
  189.     }  
  190.     /**  
  191.      * 提供精確的小數(shù)位四舍五入處理  
  192.      *  
  193.      * @param v     需要四舍五入的數(shù)字  
  194.      * @param scale 小數(shù)點(diǎn)后保留幾位  
  195.      * @return 四舍五入后的結(jié)果  
  196.      */  
  197.     public static double round(double v, int scale) {  
  198.         if (scale < 0) {  
  199.             throw new IllegalArgumentException("The scale must be a positive integer or zero");  
  200.         }  
  201.         BigDecimal b = new BigDecimal(Double.toString(v));  
  202.         return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();  
  203.     }  
  204.     /**  
  205.      * 提供精確的小數(shù)位四舍五入處理  
  206.      *  
  207.      * @param v     需要四舍五入的數(shù)字  
  208.      * @param scale 小數(shù)點(diǎn)后保留幾位  
  209.      * @return 四舍五入后的結(jié)果  
  210.      */  
  211.     public static String round(String v, int scale) {  
  212.         if (scale < 0) {  
  213.             throw new IllegalArgumentException(  
  214.                     "The scale must be a positive integer or zero");  
  215.         }  
  216.         BigDecimal b = new BigDecimal(v);  
  217.         return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();  
  218.     }  
  219.     /**  
  220.      * 取余數(shù)  
  221.      *  
  222.      * @param v1    被除數(shù)  
  223.      * @param v2    除數(shù)  
  224.      * @param scale 小數(shù)點(diǎn)后保留幾位  
  225.      * @return 余數(shù)  
  226.      */  
  227.     public static String remainder(String v1, String v2, int scale) {  
  228.         if (scale < 0) {  
  229.             throw new IllegalArgumentException(  
  230.                     "The scale must be a positive integer or zero");  
  231.         }  
  232.         BigDecimal b1 = new BigDecimal(v1);  
  233.         BigDecimal b2 = new BigDecimal(v2);  
  234.         return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();  
  235.     }  
  236.     /**  
  237.      * 取余數(shù)  BigDecimal  
  238.      *  
  239.      * @param v1    被除數(shù)  
  240.      * @param v2    除數(shù)  
  241.      * @param scale 小數(shù)點(diǎn)后保留幾位  
  242.      * @return 余數(shù)  
  243.      */  
  244.     public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {  
  245.         if (scale < 0) {  
  246.             throw new IllegalArgumentException(  
  247.                     "The scale must be a positive integer or zero");  
  248.         }  
  249.         return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);  
  250.     }  
  251.     /**  
  252.      * 比較大小  
  253.      *  
  254.      * @param v1 被比較數(shù)  
  255.      * @param v2 比較數(shù)  
  256.      * @return 如果v1 大于v2 則 返回true 否則false  
  257.      */  
  258.     public static boolean compare(String v1, String v2) {  
  259.         BigDecimal b1 = new BigDecimal(v1);  
  260.         BigDecimal b2 = new BigDecimal(v2);  
  261.         int bj = b1.compareTo(b2);  
  262.         boolean res;  
  263.         if (bj > 0)  
  264.             res = true 
  265.         else  
  266.             res = false 
  267.         return res;  
  268.     }  
  269.  

 

責(zé)任編輯:龐桂玉 來源: Java知音
相關(guān)推薦

2018-09-29 15:34:34

JavaList接口

2023-12-01 11:13:50

JavaTreeSet

2023-06-30 08:10:14

JavaBigDecimal

2016-05-04 10:36:42

iossdwebimage開發(fā)

2025-01-20 00:00:00

反射Java語言

2022-09-22 14:55:31

前端JavaScripthis

2022-09-26 13:10:17

JavaScriptthis

2025-04-01 08:00:00

curl開發(fā)運(yùn)維

2018-12-21 11:24:55

Java時(shí)間處理編程語言

2021-11-26 08:07:16

MySQL SQL 語句數(shù)據(jù)庫

2020-12-18 08:59:51

蘋果iCloud儲(chǔ)存照片

2020-03-02 14:55:02

JavaBigDecimalAPI

2024-12-27 09:29:09

2025-02-14 08:30:49

SpringJava開發(fā)

2019-07-25 12:46:32

Java高并發(fā)編程語言

2023-11-01 13:48:00

反射java

2021-09-08 07:49:35

Dubbo連接控制

2023-04-28 07:49:13

Javawaitsleep

2018-04-27 15:30:53

Java三目運(yùn)算符

2021-05-21 12:36:16

限流代碼Java
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號