<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    公司新來一個同事,把 BigDecimal 運用的爐火純青!

    共 27875字,需瀏覽 56分鐘

     ·

    2024-06-14 17:24

    點擊關注公眾號,Java干貨及時送達

    來源:cnblogs.com/zhangyinhua/p/11545305.html

    一、BigDecimal概述

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

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

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

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

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

    • BigDecimal(int)

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

    • BigDecimal(double)

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

    • BigDecimal(long)

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

    • BigDecimal(String)

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

    2.2、使用問題分析

    使用示例:

    BigDecimal a =new BigDecimal(0.1);
    System.out.println("a values is:"+a);
    System.out.println("=====================");
    BigDecimal b =new BigDecimal("0.1");
    System.out.println("b values is:"+b);

    結果示例:

    a values is:0.1000000000000000055511151231257827021181583404541015625
    =====================
    b values is:0.1

    原因分析:

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

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

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

    三、BigDecimal常用方法詳解

    3.1、常用方法

    • add(BigDecimal)

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

    • subtract(BigDecimal)

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

    • multiply(BigDecimal)

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

    • divide(BigDecimal)

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

    • toString()

    將BigDecimal對象中的值轉換成字符串

    • doubleValue()

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

    • floatValue()

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

    • longValue()

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

    • intValue()

    將BigDecimal對象中的值轉換成整數(shù),插播一條:如果你近期準備面試跳槽,點擊Java面試庫小程序刷題吧,共 2500+ 道,幾乎覆蓋了所有主流 Java 技術面試題。

    3.2、BigDecimal大小比較

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

    int a = bigdemical.compareTo(bigdemical2)

    返回結果分析:

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

    舉例:a大于等于b

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

    四、BigDecimal格式化

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

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

    推薦一個開源免費的 Spring Boot 實戰(zhàn)項目:

    https://github.com/javastacks/spring-boot-best-practice

    NumberFormat currency = NumberFormat.getCurrencyInstance(); //建立貨幣格式化引用
    NumberFormat percent = NumberFormat.getPercentInstance();  //建立百分比格式化引用
    percent.setMaximumFractionDigits(3); //百分比小數(shù)點最多3位

    BigDecimal loanAmount = new BigDecimal("15000.48"); //貸款金額
    BigDecimal interestRate = new BigDecimal("0.008"); //利率
    BigDecimal interest = loanAmount.multiply(interestRate); //相乘

    System.out.println("貸款金額:\t" + currency.format(loanAmount));
    System.out.println("利率:\t" + percent.format(interestRate));
    System.out.println("利息:\t" + currency.format(interest));

    結果:

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

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

    public class NumberFormat {

        public static void main(String[] s){
            System.out.println(formatToNumber(new BigDecimal("3.435")));
            System.out.println(formatToNumber(new BigDecimal(0)));
            System.out.println(formatToNumber(new BigDecimal("0.00")));
            System.out.println(formatToNumber(new BigDecimal("0.001")));
            System.out.println(formatToNumber(new BigDecimal("0.006")));
            System.out.println(formatToNumber(new BigDecimal("0.206")));
        }
        /**
         * @desc 1.0~1之間的BigDecimal小數(shù),格式化后失去前面的0,則前面直接加上0。
         * 2.傳入的參數(shù)等于0,則直接返回字符串"0.00"
         * 3.大于1的小數(shù),直接格式化返回字符串
         * @param obj傳入的小數(shù)
         * @return
         */
        public static String formatToNumber(BigDecimal obj) {
            DecimalFormat df = new DecimalFormat("#.00");
            if(obj.compareTo(BigDecimal.ZERO)==0) {
                return "0.00";
            }else if(obj.compareTo(BigDecimal.ZERO)>0&&obj.compareTo(new BigDecimal(1))<0){
                return "0"+df.format(obj).toString();
            }else {
                return df.format(obj).toString();
            }
        }
    }

    結果為:

    3.44
    0.00
    0.00
    0.00
    0.01
    0.21

    五、BigDecimal常見異常

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

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

    原因分析:

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

    解決方法:

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

    另外,如果你近期準備面試跳槽,建議在Java面試庫小程序在線刷題,涵蓋 2000+ 道 Java 面試題,幾乎覆蓋了所有主流技術面試題。

    六、BigDecimal總結

    6.1、總結

    在需要精確的小數(shù)計算時再使用BigDecimal,BigDecimal的性能比double和float差,在處理龐大,復雜的運算時尤為明顯。故一般精度的計算沒必要使用BigDecimal。盡量使用參數(shù)類型為String的構造函數(shù)。

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

    6.2、工具類推薦

    package com.vivo.ars.util;
    import java.math.BigDecimal;

    /**
     * 用于高精確處理常用的數(shù)學運算
     */
    public class ArithmeticUtils {
        //默認除法運算精度
        private static final int DEF_DIV_SCALE = 10;

        /**
         * 提供精確的加法運算
         *
         * @param v1 被加數(shù)
         * @param v2 加數(shù)
         * @return 兩個參數(shù)的和
         */

        public static double add(double v1, double v2) {
            BigDecimal b1 = new BigDecimal(Double.toString(v1));
            BigDecimal b2 = new BigDecimal(Double.toString(v2));
            return b1.add(b2).doubleValue();
        }

        /**
         * 提供精確的加法運算
         *
         * @param v1 被加數(shù)
         * @param v2 加數(shù)
         * @return 兩個參數(shù)的和
         */
        public static BigDecimal add(String v1, String v2) {
            BigDecimal b1 = new BigDecimal(v1);
            BigDecimal b2 = new BigDecimal(v2);
            return b1.add(b2);
        }

        /**
         * 提供精確的加法運算
         *
         * @param v1    被加數(shù)
         * @param v2    加數(shù)
         * @param scale 保留scale 位小數(shù)
         * @return 兩個參數(shù)的和
         */
        public static String add(String v1, String v2, int scale) {
            if (scale < 0) {
                throw new IllegalArgumentException(
                        "The scale must be a positive integer or zero");
            }
            BigDecimal b1 = new BigDecimal(v1);
            BigDecimal b2 = new BigDecimal(v2);
            return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
        }

        /**
         * 提供精確的減法運算
         *
         * @param v1 被減數(shù)
         * @param v2 減數(shù)
         * @return 兩個參數(shù)的差
         */
        public static double sub(double v1, double v2) {
            BigDecimal b1 = new BigDecimal(Double.toString(v1));
            BigDecimal b2 = new BigDecimal(Double.toString(v2));
            return b1.subtract(b2).doubleValue();
        }

        /**
         * 提供精確的減法運算。
         *
         * @param v1 被減數(shù)
         * @param v2 減數(shù)
         * @return 兩個參數(shù)的差
         */
        public static BigDecimal sub(String v1, String v2) {
            BigDecimal b1 = new BigDecimal(v1);
            BigDecimal b2 = new BigDecimal(v2);
            return b1.subtract(b2);
        }

        /**
         * 提供精確的減法運算
         *
         * @param v1    被減數(shù)
         * @param v2    減數(shù)
         * @param scale 保留scale 位小數(shù)
         * @return 兩個參數(shù)的差
         */
        public static String sub(String v1, String v2, int scale) {
            if (scale < 0) {
                throw new IllegalArgumentException(
                        "The scale must be a positive integer or zero");
            }
            BigDecimal b1 = new BigDecimal(v1);
            BigDecimal b2 = new BigDecimal(v2);
            return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
        }

        /**
         * 提供精確的乘法運算
         *
         * @param v1 被乘數(shù)
         * @param v2 乘數(shù)
         * @return 兩個參數(shù)的積
         */
        public static double mul(double v1, double v2) {
            BigDecimal b1 = new BigDecimal(Double.toString(v1));
            BigDecimal b2 = new BigDecimal(Double.toString(v2));
            return b1.multiply(b2).doubleValue();
        }

        /**
         * 提供精確的乘法運算
         *
         * @param v1 被乘數(shù)
         * @param v2 乘數(shù)
         * @return 兩個參數(shù)的積
         */
        public static BigDecimal mul(String v1, String v2) {
            BigDecimal b1 = new BigDecimal(v1);
            BigDecimal b2 = new BigDecimal(v2);
            return b1.multiply(b2);
        }

        /**
         * 提供精確的乘法運算
         *
         * @param v1    被乘數(shù)
         * @param v2    乘數(shù)
         * @param scale 保留scale 位小數(shù)
         * @return 兩個參數(shù)的積
         */
        public static double mul(double v1, double v2, int scale) {
            BigDecimal b1 = new BigDecimal(Double.toString(v1));
            BigDecimal b2 = new BigDecimal(Double.toString(v2));
            return round(b1.multiply(b2).doubleValue(), scale);
        }

        /**
         * 提供精確的乘法運算
         *
         * @param v1    被乘數(shù)
         * @param v2    乘數(shù)
         * @param scale 保留scale 位小數(shù)
         * @return 兩個參數(shù)的積
         */
        public static String mul(String v1, String v2, int scale) {
            if (scale < 0) {
                throw new IllegalArgumentException(
                        "The scale must be a positive integer or zero");
            }
            BigDecimal b1 = new BigDecimal(v1);
            BigDecimal b2 = new BigDecimal(v2);
            return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
        }

        /**
         * 提供(相對)精確的除法運算,當發(fā)生除不盡的情況時,精確到
         * 小數(shù)點以后10位,以后的數(shù)字四舍五入
         *
         * @param v1 被除數(shù)
         * @param v2 除數(shù)
         * @return 兩個參數(shù)的商
         */

        public static double div(double v1, double v2) {
            return div(v1, v2, DEF_DIV_SCALE);
        }

        /**
         * 提供(相對)精確的除法運算。當發(fā)生除不盡的情況時,由scale參數(shù)指
         * 定精度,以后的數(shù)字四舍五入
         *
         * @param v1    被除數(shù)
         * @param v2    除數(shù)
         * @param scale 表示表示需要精確到小數(shù)點以后幾位。
         * @return 兩個參數(shù)的商
         */
        public static double div(double v1, double v2, int scale) {
            if (scale < 0) {
                throw new IllegalArgumentException("The scale must be a positive integer or zero");
            }
            BigDecimal b1 = new BigDecimal(Double.toString(v1));
            BigDecimal b2 = new BigDecimal(Double.toString(v2));
            return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
        }

        /**
         * 提供(相對)精確的除法運算。當發(fā)生除不盡的情況時,由scale參數(shù)指
         * 定精度,以后的數(shù)字四舍五入
         *
         * @param v1    被除數(shù)
         * @param v2    除數(shù)
         * @param scale 表示需要精確到小數(shù)點以后幾位
         * @return 兩個參數(shù)的商
         */
        public static String div(String v1, String v2, int scale) {
            if (scale < 0) {
                throw new IllegalArgumentException("The scale must be a positive integer or zero");
            }
            BigDecimal b1 = new BigDecimal(v1);
            BigDecimal b2 = new BigDecimal(v1);
            return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
        }

        /**
         * 提供精確的小數(shù)位四舍五入處理
         *
         * @param v     需要四舍五入的數(shù)字
         * @param scale 小數(shù)點后保留幾位
         * @return 四舍五入后的結果
         */
        public static double round(double v, int scale) {
            if (scale < 0) {
                throw new IllegalArgumentException("The scale must be a positive integer or zero");
            }
            BigDecimal b = new BigDecimal(Double.toString(v));
            return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
        }

        /**
         * 提供精確的小數(shù)位四舍五入處理
         *
         * @param v     需要四舍五入的數(shù)字
         * @param scale 小數(shù)點后保留幾位
         * @return 四舍五入后的結果
         */
        public static String round(String v, int scale) {
            if (scale < 0) {
                throw new IllegalArgumentException(
                        "The scale must be a positive integer or zero");
            }
            BigDecimal b = new BigDecimal(v);
            return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
        }

        /**
         * 取余數(shù)
         *
         * @param v1    被除數(shù)
         * @param v2    除數(shù)
         * @param scale 小數(shù)點后保留幾位
         * @return 余數(shù)
         */
        public static String remainder(String v1, String v2, int scale) {
            if (scale < 0) {
                throw new IllegalArgumentException(
                        "The scale must be a positive integer or zero");
            }
            BigDecimal b1 = new BigDecimal(v1);
            BigDecimal b2 = new BigDecimal(v2);
            return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
        }

        /**
         * 取余數(shù)  BigDecimal
         *
         * @param v1    被除數(shù)
         * @param v2    除數(shù)
         * @param scale 小數(shù)點后保留幾位
         * @return 余數(shù)
         */
        public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {
            if (scale < 0) {
                throw new IllegalArgumentException(
                        "The scale must be a positive integer or zero");
            }
            return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);
        }

        /**
         * 比較大小
         *
         * @param v1 被比較數(shù)
         * @param v2 比較數(shù)
         * @return 如果v1 大于v2 則 返回true 否則false
         */
        public static boolean compare(String v1, String v2) {
            BigDecimal b1 = new BigDecimal(v1);
            BigDecimal b2 = new BigDecimal(v2);
            int bj = b1.compareTo(b2);
            boolean res;
            if (bj > 0)
                res = true;
            else
                res = false;
            return res;
        }
    }

         

      

            

             

    1、前MySQL工程師發(fā)聲:再不悔改,Oracle將殺死MySQL!

    2、首款配備驍龍X Elite處理器的Linux筆記本:采用KDE Plasma桌面環(huán)境、計劃年底推出

    3、解決日志開關需求:SpringBoot 實現(xiàn)熱插拔 AOP

    4、為什么國外JetBrains做 IDE 就可以養(yǎng)活自己,國內不行?區(qū)別在哪?

    5、MySQL 你沒見過的字符串函數(shù)

    6、別再手動拼接 SQL 了,MyBatis 動態(tài) SQL 寫法應有盡有,建議收藏!

    點在看

    瀏覽 134
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報
    評論
    圖片
    表情
    推薦
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    日本成人网址 | 手机看91AV | 请立即播放黑人大屌日白人小嫩逼的视频 | 操逼视频无码免费www | 大香蕉啪啪啪 |