最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?BigDecimal正確用法詳解

 更新時間:2022年10月03日 11:07:57   作者:Dily_Su  
Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數(shù)進行精確的運算。雙精度浮點型變量double可以處理16位有效數(shù),但在實際應(yīng)用中,可能需要對更大或者更小的數(shù)進行運算和處理

一、背景

BigDecimal 平時主要用于計算金錢時,其自身提供了很多的構(gòu)造方法,但是這些構(gòu)造方法使用不當(dāng)會造成精度丟失,從而引起事故。

二、事故案例

1、問題

收銀臺計算商品價格報錯,導(dǎo)致訂單無法支付

2、問題復(fù)現(xiàn)

public static void main(String[] args) {
    BigDecimal bigDecimal=new BigDecimal(88);
    System.out.println(bigDecimal);
    bigDecimal=new BigDecimal("8.8");
    System.out.println(bigDecimal);
    bigDecimal=new BigDecimal(8.8);
    System.out.println(bigDecimal);
}

3、源碼分析

public static long doubleToLongBits(double value) {
    long result = doubleToRawLongBits(value);
    // Check for NaN based on values of bit fields, maximum
    // exponent and nonzero significand.
    if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
          DoubleConsts.EXP_BIT_MASK) &&
         (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
        result = 0x7ff8000000000000L;
    return result;
}

問題就處在 doubleToRawLongBits 這個方法上,在 jdk 中 double 類(float 與 int 對應(yīng))中提供了 double 與 long 轉(zhuǎn)換,doubleToRawLongBits 就是將 double 轉(zhuǎn)換為 long,這個方法是原始方法(底層不是 java 實現(xiàn),是 c++ 實現(xiàn)的)。

4、原因分析

在 java 中 BigDecimal 處理數(shù)據(jù)時把十進制小數(shù)擴大 N 倍讓它在整數(shù)上進行計算,并保留相應(yīng)的精度信息。

  1. float 和 double 類型,主要是為了科學(xué)計算和工程計算而設(shè)計的,之所以執(zhí)行二進制浮點運算,是為了在廣泛的數(shù)值范圍上提供較為精確的快速近和計算。
  2. 并沒有提供完全精確的結(jié)果,所以不應(yīng)該被用于精確的結(jié)果的場合。
  3. 當(dāng)浮點數(shù)達到一定大的數(shù),就會自動使用科學(xué)計數(shù)法,這樣的表示只是近似真實數(shù)而不等于真實數(shù)。
  4. 當(dāng)十進制小數(shù)位轉(zhuǎn)換二進制的時候也會出現(xiàn)無限循環(huán)或者超過浮點數(shù)尾數(shù)的長度。

三、總結(jié)

在設(shè)計到精度計算時,我們盡量使用 String 類型來進行轉(zhuǎn)換,而且涉及到 BigDecimal 的計算,要使用其對應(yīng)方法進行計算。

四、工具類

這里封裝一個 BigDecimal 工具類

public class BigDecimalUtils {
    /**
     * double 加
     *
     * @param v1 加數(shù)
     * @param v2 加數(shù)
     * @return 和
     */
    public static BigDecimal doubleAdd(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2);
    }
    /**
     * float 加
     *
     * @param v1 加數(shù)
     * @param v2 加數(shù)
     * @return 和
     */
    public static BigDecimal floatAdd(float v1, float v2) {
        BigDecimal b1 = new BigDecimal(Float.toString(v1));
        BigDecimal b2 = new BigDecimal(Float.toString(v2));
        return b1.add(b2);
    }
    /**
     * double 減
     *
     * @param v1 被減數(shù)
     * @param v2 減數(shù)
     * @return 差
     */
    public static BigDecimal doubleSub(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2);
    }
    /**
     * float 減
     *
     * @param v1 被減數(shù)
     * @param v2 減數(shù)
     * @return 差
     */
    public static BigDecimal floatSub(float v1, float v2) {
        BigDecimal b1 = new BigDecimal(Float.toString(v1));
        BigDecimal b2 = new BigDecimal(Float.toString(v2));
        return b1.subtract(b2);
    }
    /**
     * double 乘
     *
     * @param v1 因數(shù)
     * @param v2 因數(shù)
     * @return 積
     */
    public static BigDecimal doubleMul(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2);
    }
    /**
     * float 乘
     *
     * @param v1 因數(shù)
     * @param v2 因數(shù)
     * @return 積
     */
    public static BigDecimal floatMul(float v1, float v2) {
        BigDecimal b1 = new BigDecimal(Float.toString(v1));
        BigDecimal b2 = new BigDecimal(Float.toString(v2));
        return b1.multiply(b2);
    }
    /**
     * double 除
     *
     * @param v1 被除數(shù)
     * @param v2 除數(shù)
     * @return 商
     */
    public static BigDecimal doubleDiv(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        // 保留小數(shù)點后兩位 ROUND_HALF_UP = 四舍五入
        return b1.divide(b2, 2, RoundingMode.HALF_UP);
    }
    /**
     * float 除
     *
     * @param v1 被除數(shù)
     * @param v2 除數(shù)
     * @return 商
     */
    public static BigDecimal floatDiv(float v1, float v2) {
        BigDecimal b1 = new BigDecimal(Float.toString(v1));
        BigDecimal b2 = new BigDecimal(Float.toString(v2));
        // 保留小數(shù)點后兩位 ROUND_HALF_UP = 四舍五入
        return b1.divide(b2, 2, RoundingMode.HALF_UP);
    }
    /**
     * double<br>
     * 比較v1 v2大小
     *
     * @param v1
     * @param v2
     * @return v1>v2 return 1  v1=v2 return 0 v1<v2 return -1
     */
    public static int doubleCompareTo(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.compareTo(b2);
    }
    /**
     * float<br>
     * 比較v1 v2大小
     *
     * @param v1
     * @param v2
     * @return v1>v2 return 1  v1=v2 return 0 v1<v2 return -1
     */
    public static int floatCompareTo(float v1, float v2) {
        BigDecimal b1 = new BigDecimal(Float.toString(v1));
        BigDecimal b2 = new BigDecimal(Float.toString(v2));
        return b1.compareTo(b2);
    }
}

到此這篇關(guān)于Java BigDecimal正確用法詳解的文章就介紹到這了,更多相關(guān)Java BigDecimal內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java如何提高大量數(shù)據(jù)的處理性能

    Java如何提高大量數(shù)據(jù)的處理性能

    在Java中提高大量數(shù)據(jù)的處理性能,可以從多個角度進行優(yōu)化,包括選擇合適的數(shù)據(jù)結(jié)構(gòu),使用多線程和并發(fā)處理等,下面我們來看看Java提高大量數(shù)據(jù)的處理性能的實用技巧吧
    2025-01-01
  • Redis 訂閱發(fā)布_Jedis實現(xiàn)方法

    Redis 訂閱發(fā)布_Jedis實現(xiàn)方法

    下面小編就為大家?guī)硪黄猂edis 訂閱發(fā)布_Jedis實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • Java基礎(chǔ)之教你如何正確運用依賴注入

    Java基礎(chǔ)之教你如何正確運用依賴注入

    最近發(fā)現(xiàn)很多使用Spring框架的Java代碼存在依賴注入方式的誤用,甚至是濫用.因此整理了這篇文章,歡迎大家一起探討,需要的朋友可以參考下
    2021-05-05
  • java 全角半角字符轉(zhuǎn)換的方法實例

    java 全角半角字符轉(zhuǎn)換的方法實例

    這篇文章主要介紹了java 全角半角字符轉(zhuǎn)換的方法,大家參考使用吧
    2013-11-11
  • 繼承WebMvcConfigurationSupport后自動配置不生效及如何配置攔截器

    繼承WebMvcConfigurationSupport后自動配置不生效及如何配置攔截器

    這篇文章主要介紹了繼承WebMvcConfigurationSupport后自動配置不生效及如何配置攔截器,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Java基本語法小白入門級

    Java基本語法小白入門級

    Java基本語法就是指java中的規(guī)則,也是一種語言規(guī)則,規(guī)范,同時也能讓您在后面的學(xué)習(xí)中避免不必要的一些錯誤和麻煩,是您學(xué)好java必修的第一門課程
    2023-05-05
  • Java執(zhí)行JS腳本工具

    Java執(zhí)行JS腳本工具

    今天小編就為大家分享一篇關(guān)于Java執(zhí)行JS腳本工具,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • 基于SpringBoot實現(xiàn)Web應(yīng)用的登錄與退出功能

    基于SpringBoot實現(xiàn)Web應(yīng)用的登錄與退出功能

    登錄與退出功能作為 Web 應(yīng)用中的基礎(chǔ)且重要的組成部分,直接關(guān)系到用戶的安全和隱私保護,所以本文給大家介紹了基于SpringBoot實現(xiàn)Web應(yīng)用的登錄與退出功能,文中有詳細的代碼供大家參考,需要的朋友可以參考下
    2024-04-04
  • SpringBoot啟動并初始化執(zhí)行sql腳本問題

    SpringBoot啟動并初始化執(zhí)行sql腳本問題

    這篇文章主要介紹了SpringBoot啟動并初始化執(zhí)行sql腳本問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Java實現(xiàn)ATM銀行管理系統(tǒng)(控制臺版本)

    Java實現(xiàn)ATM銀行管理系統(tǒng)(控制臺版本)

    這篇文章主要為大家詳細介紹了如何利用Java語言實現(xiàn)控制臺版本的ATM銀行管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06

最新評論

拉孜县| 民勤县| 兰西县| 和硕县| 泌阳县| 福泉市| 石家庄市| 武穴市| 岑溪市| 宾川县| 曲松县| 道孚县| 海丰县| 兖州市| 东阿县| 临武县| 安阳县| 安阳市| 大洼县| 冀州市| 宜良县| 阳春市| 嘉鱼县| 永福县| 泰州市| 福贡县| 平原县| 灯塔市| 康乐县| 布拖县| 鸡西市| 施甸县| 上栗县| 达州市| 长子县| 观塘区| 韶山市| 屏边| 高要市| 定襄县| 甘肃省|