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

Java中double精度丟失問題原因及解決辦法

 更新時間:2024年01月06日 09:05:02   作者:雨汨  
使用Java double進行運算時,經(jīng)常出現(xiàn)精度丟失的問題,總是在一個正確的結果左右偏0.0000**1,這篇文章主要給大家介紹了關于Java中double精度丟失問題原因及解決辦法,需要的朋友可以參考下

double類型精度丟失問題:

0.1*0.1使用計算器計算是0.01,代碼里卻是0.010000000000000002

public class HelloWorld {
    public static void main(String []args) {
       double number1 = 0.1;
	   double number2 = 0.1;
	   double result = number1 * number2 ;
	   System.out.println("使用double運算結果: "+result);
    }
}

為什么會這樣呢?這就是精度丟失問題造成的。

為什么會出現(xiàn)精度丟失?

因為計算機只能識別0和1,即二進制,無論哪種編程語言,都需要翻譯成二進制才能被計算機識別。

很多人還知道這樣一句話:這種舍入誤差的主要原因是浮點數(shù)值采用二進制系統(tǒng)表示, 而在二進制系統(tǒng)中無法精確地表示分數(shù) 1/10。這就好像十進制無法精確地表示分數(shù) 1/3—樣。

針對十進制,1除以3是除不盡的。很好理解,因為我們一直接觸的就是十進制,等于0.333333… 很好理解

但是:二進制系統(tǒng)中無法精確地表示分數(shù) 1/10。為啥呢。就有點不理解了

《Java核心技術卷》書上也是這么寫的。

十進制 轉(zhuǎn)二進制(每次將小數(shù)部分乘2,取出整數(shù)部分,如果小數(shù)部分為0,就可以停止這個過程):十進制0.1

0.1*2=0.2
0.2*2=0.4
0.4*2=0.8
0.8*2=1.6

0.6*2=1.2
0.2*2=0.4
0.4*2=0.8
//... 應該已經(jīng)發(fā)現(xiàn),上面的過程已經(jīng)開始循環(huán),小數(shù)部分永遠不能為0

怎么解決精度丟失問題?

在商城里面計算訂單金額的時候,我們就不得不解決這個問題了,這時候就用到了BigDecimal

BigDecimal類位于java.math包下,用于對超過16位有效位的數(shù)進行精確的運算。

一般來說,double類型的變量可以處理16位有效數(shù),

但實際應用中,如果超過16位,就需要BigDecimal類來操作

new BigDecimal(double val)

new BigDecimal(String val)

BigDecimal.valueOf(double val)

將double轉(zhuǎn)為BigDecimal的時候,需要先把double轉(zhuǎn)換為字符串,然后再作為BigDecimal(String val)構造函數(shù)的參數(shù),這樣才能避免出現(xiàn)精度問題。

import java.math.BigDecimal;

public class BigDecimalUtil {

    /**
     * double類型的加法運算(不需要舍入)
     * @param d1
     * @param d2
     * @return 不加doubleValue()則, 返回BigDecimal對象
     */
    public static double addDouble(double d1, double d2) {
        BigDecimal p1 = new BigDecimal(Double.toString(d1));
        BigDecimal p2 = new BigDecimal(Double.toString(d2));
        return p1.add(p2).doubleValue();
    }

    /**
     * double類型的加法運算(需要舍入)
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return 不加doubleValue()則, 返回BigDecimal對象
     */
    public static double addDouble(double d1, double d2, int scale) {
        BigDecimal p1 = new BigDecimal(Double.toString(d1));
        BigDecimal p2 = new BigDecimal(Double.toString(d2));
        return p1.add(p2).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * double類型的超大數(shù)值加法運算(超過50 0000)(需要舍入)
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return 返回字符串,不然double數(shù)字會轉(zhuǎn)成科學計數(shù)法顯示
     */
    public static String addDoubleToStr(double d1, double d2, int scale) {
        BigDecimal p1 = new BigDecimal(Double.toString(d1));
        BigDecimal p2 = new BigDecimal(Double.toString(d2));
        return p1.add(p2).setScale(scale, BigDecimal.ROUND_HALF_UP).toPlainString();
    }

    /**
     * double類型的減法運算
     * @param d1
     * @param d2
     * @return 不加doubleValue()則, 返回BigDecimal對象
     */
    public static double subtractDouble(double d1, double d2) {
        BigDecimal p1 = new BigDecimal(Double.toString(d1));
        BigDecimal p2 = new BigDecimal(Double.toString(d2));
        return p1.subtract(p2).doubleValue();
    }

    /**
     * double類型的減法運算(需要舍入)
     * @param d1
     * @param d2
     * @param scale  保留scale位小數(shù)
     * @return  不加doubleValue()則, 返回BigDecimal對象
     */
    public static double subtractDouble(double d1, double d2, int scale) {
        BigDecimal p1 = new BigDecimal(Double.toString(d1));
        BigDecimal p2 = new BigDecimal(Double.toString(d2));
        return p1.subtract(p2).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * double類型的超大數(shù)值減法運算(需要舍入)
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return  返回字符串,不然double數(shù)字會轉(zhuǎn)成科學計數(shù)法顯示
     */
    public static String subtractDoubleToStr(double d1, double d2, int scale) {
        BigDecimal p1 = new BigDecimal(Double.toString(d1));
        BigDecimal p2 = new BigDecimal(Double.toString(d2));
        return p1.subtract(p2).setScale(scale, BigDecimal.ROUND_HALF_UP).toPlainString();
    }

    /**
     * double類型的乘法運算
     *
     * @param d1
     * @param d2
     * @return 不加doubleValue()則, 返回BigDecimal對象
     */
    public static double multiplyDouble(double d1, double d2) {
        BigDecimal p1 = new BigDecimal(Double.toString(d1));
        BigDecimal p2 = new BigDecimal(Double.toString(d2));
        return p1.multiply(p2).doubleValue();
    }

    /**
     * double類型的乘法運算(需要舍入)
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return 不加doubleValue()則, 返回BigDecimal對象
     */
    public static double multiplyDouble(double d1, double d2, int scale) {
        BigDecimal p1 = new BigDecimal(Double.toString(d1));
        BigDecimal p2 = new BigDecimal(Double.toString(d2));
        return p1.multiply(p2).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * double類型的超大數(shù)值的乘法運算(需要舍入)
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return 返回字符串,不然double數(shù)字會轉(zhuǎn)成科學計數(shù)法顯示
     */
    public static String multiplyDoubleToStr(double d1, double d2, int scale) {
        BigDecimal p1 = new BigDecimal(Double.toString(d1));
        BigDecimal p2 = new BigDecimal(Double.toString(d2));
        return p1.multiply(p2).setScale(scale, BigDecimal.ROUND_HALF_UP).toPlainString();
    }

    /**
     * double類型的除法運算(需要舍入)
     *
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return 不加doubleValue()則, 返回BigDecimal對象
     */
    public static double divideDouble(double d1, double d2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("Parameter error");
        }
        BigDecimal p1 = new BigDecimal(Double.toString(d1));
        BigDecimal p2 = new BigDecimal(Double.toString(d2));
        return p1.divide(p2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * double類型的超大數(shù)值的除法運算(需要舍入)
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return 返回字符串,不然double數(shù)字會轉(zhuǎn)成科學計數(shù)法顯示
     */
    public static String divideDoubleToStr(double d1, double d2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("Parameter error");
        }
        BigDecimal p1 = new BigDecimal(Double.toString(d1));
        BigDecimal p2 = new BigDecimal(Double.toString(d2));
        return p1.divide(p2, scale, BigDecimal.ROUND_HALF_UP).toPlainString();
    }
}

各個roundingMode詳解如下:

  • ROUND_UP:非0時,舍棄小數(shù)后(整數(shù)部分)加1,比如12.49結果為13,-12.49結果為 -13
  • ROUND_DOWN:直接舍棄小數(shù)
  • ROUND_CEILING:如果 BigDecimal 是正的,則做 ROUND_UP 操作;如果為負,則做 ROUND_DOWN 操作 (一句話:取附近較大的整數(shù))
  • ROUND_FLOOR: 如果 BigDecimal 是正的,則做 ROUND_DOWN 操作;如果為負,則做 ROUND_UP 操作(一句話:取附近較小的整數(shù))
  • ROUND_HALF_UP:四舍五入(取更近的整數(shù))
  • ROUND_HALF_DOWN:跟ROUND_HALF_UP 差別僅在于0.5時會向下取整
  • ROUND_HALF_EVEN:取最近的偶數(shù)
  • ROUND_UNNECESSARY:不需要取整,如果存在小數(shù)位,就拋ArithmeticException 異常

總結

到此這篇關于Java中double精度丟失問題原因及解決辦法的文章就介紹到這了,更多相關Java double精度丟失問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • java設計模式之外觀模式學習筆記

    java設計模式之外觀模式學習筆記

    這篇文章主要為大家詳細介紹了java設計模式之外觀模式學習筆記,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • SpringBoot整合阿里云OSS對象存儲服務的實現(xiàn)

    SpringBoot整合阿里云OSS對象存儲服務的實現(xiàn)

    這篇文章主要介紹了SpringBoot整合阿里云OSS對象存儲服務的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08
  • SpringBoot使用Validation實現(xiàn)接口校驗的超全使用指南

    SpringBoot使用Validation實現(xiàn)接口校驗的超全使用指南

    這篇文章主要為大家詳細介紹了SpringBoot使用Validation實現(xiàn)接口校驗的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2026-03-03
  • SpringBoot集成Nacos的項目實踐

    SpringBoot集成Nacos的項目實踐

    本文主要介紹了SpringBoot集成Nacos的項目實踐,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • SpringBoot連接Redis2種模式解析

    SpringBoot連接Redis2種模式解析

    這篇文章主要介紹了SpringBoot連接Redis2種模式解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • java web圖片上傳和文件上傳實例

    java web圖片上傳和文件上傳實例

    本篇文章主要介紹了java web圖片上傳和文件上傳實例,具有一定的參考價值,有需要的可以了解一下。
    2016-11-11
  • java中@requestMappling注解的使用

    java中@requestMappling注解的使用

    本文主要介紹了java中@requestMappling注解的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • 分模塊構建Maven工程的方法步驟

    分模塊構建Maven工程的方法步驟

    這篇文章主要介紹了分模塊構建Maven工程的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-10-10
  • Java實現(xiàn)LeetCode(組合總和)

    Java實現(xiàn)LeetCode(組合總和)

    這篇文章主要介紹了Java實現(xiàn)LeetCode(組合總數(shù)),本文通過使用java實現(xiàn)leetcode的組合總數(shù)題目和實現(xiàn)思路分析,需要的朋友可以參考下
    2021-06-06
  • maven資源過濾打包后文件變大的處理方法

    maven資源過濾打包后文件變大的處理方法

    maven目前在web上面的使用方式很普遍,而打包的方式也存在很多方式,下面這篇文章主要給大家介紹了關于maven資源過濾打包后文件變大的處理方法,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2018-07-07

最新評論

哈尔滨市| 济南市| 建始县| 安新县| 错那县| 宁波市| 富平县| 安顺市| 荣成市| 克东县| 黄平县| 杨浦区| 永寿县| 四平市| 岑溪市| 中西区| 文水县| 龙胜| 和硕县| 宜川县| 成武县| 仁怀市| 丽江市| 和林格尔县| 瑞安市| 安仁县| 称多县| 南江县| 河东区| 萝北县| 固原市| 平遥县| 彰化市| 应城市| 海原县| 武威市| 昌宁县| 留坝县| 兴宁市| 临清市| 竹山县|