亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中double精度丟失問(wèn)題原因及解決辦法

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

double類型精度丟失問(wèn)題:

0.1*0.1使用計(jì)算器計(jì)算是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運(yùn)算結(jié)果: "+result);
    }
}

為什么會(huì)這樣呢?這就是精度丟失問(wèn)題造成的。

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

因?yàn)橛?jì)算機(jī)只能識(shí)別0和1,即二進(jìn)制,無(wú)論哪種編程語(yǔ)言,都需要翻譯成二進(jìn)制才能被計(jì)算機(jī)識(shí)別。

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

針對(duì)十進(jìn)制,1除以3是除不盡的。很好理解,因?yàn)槲覀円恢苯佑|的就是十進(jìn)制,等于0.333333… 很好理解

但是:二進(jìn)制系統(tǒng)中無(wú)法精確地表示分?jǐn)?shù) 1/10。為啥呢。就有點(diǎn)不理解了

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

十進(jìn)制 轉(zhuǎn)二進(jìn)制(每次將小數(shù)部分乘2,取出整數(shù)部分,如果小數(shù)部分為0,就可以停止這個(gè)過(guò)程):十進(jìn)制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
//... 應(yīng)該已經(jīng)發(fā)現(xiàn),上面的過(guò)程已經(jīng)開(kāi)始循環(huán),小數(shù)部分永遠(yuǎn)不能為0

怎么解決精度丟失問(wèn)題?

在商城里面計(jì)算訂單金額的時(shí)候,我們就不得不解決這個(gè)問(wèn)題了,這時(shí)候就用到了BigDecimal

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

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

但實(shí)際應(yīng)用中,如果超過(guò)16位,就需要BigDecimal類來(lái)操作

new BigDecimal(double val)

new BigDecimal(String val)

BigDecimal.valueOf(double val)

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

import java.math.BigDecimal;

public class BigDecimalUtil {

    /**
     * double類型的加法運(yùn)算(不需要舍入)
     * @param d1
     * @param d2
     * @return 不加doubleValue()則, 返回BigDecimal對(duì)象
     */
    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類型的加法運(yùn)算(需要舍入)
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return 不加doubleValue()則, 返回BigDecimal對(duì)象
     */
    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ù)值加法運(yùn)算(超過(guò)50 0000)(需要舍入)
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return 返回字符串,不然double數(shù)字會(huì)轉(zhuǎn)成科學(xué)計(jì)數(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類型的減法運(yùn)算
     * @param d1
     * @param d2
     * @return 不加doubleValue()則, 返回BigDecimal對(duì)象
     */
    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類型的減法運(yùn)算(需要舍入)
     * @param d1
     * @param d2
     * @param scale  保留scale位小數(shù)
     * @return  不加doubleValue()則, 返回BigDecimal對(duì)象
     */
    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ù)值減法運(yùn)算(需要舍入)
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return  返回字符串,不然double數(shù)字會(huì)轉(zhuǎn)成科學(xué)計(jì)數(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類型的乘法運(yùn)算
     *
     * @param d1
     * @param d2
     * @return 不加doubleValue()則, 返回BigDecimal對(duì)象
     */
    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類型的乘法運(yùn)算(需要舍入)
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return 不加doubleValue()則, 返回BigDecimal對(duì)象
     */
    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ù)值的乘法運(yùn)算(需要舍入)
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return 返回字符串,不然double數(shù)字會(huì)轉(zhuǎn)成科學(xué)計(jì)數(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類型的除法運(yùn)算(需要舍入)
     *
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return 不加doubleValue()則, 返回BigDecimal對(duì)象
     */
    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ù)值的除法運(yùn)算(需要舍入)
     * @param d1
     * @param d2
     * @param scale 保留scale位小數(shù)
     * @return 返回字符串,不然double數(shù)字會(huì)轉(zhuǎn)成科學(xué)計(jì)數(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();
    }
}

各個(gè)roundingMode詳解如下:

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

總結(jié)

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

相關(guān)文章

  • Java使用kafka發(fā)送和生產(chǎn)消息的示例

    Java使用kafka發(fā)送和生產(chǎn)消息的示例

    本篇文章主要介紹了Java使用kafka發(fā)送和生產(chǎn)消息的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • Spring使用@Autowired為抽象父類注入依賴代碼實(shí)例

    Spring使用@Autowired為抽象父類注入依賴代碼實(shí)例

    這篇文章主要介紹了Spring使用@Autowired為抽象父類注入依賴代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 全面解析Java中的引用類型

    全面解析Java中的引用類型

    在Java中對(duì)象以引用來(lái)指向JVM的內(nèi)存區(qū)塊,這里我們總結(jié)了強(qiáng)引用、軟引用、弱引用和假象引用(幽靈引用),下面就具體來(lái)全面解析Java中的引用類型:
    2016-05-05
  • idea打包不出現(xiàn)target的原因及解決

    idea打包不出現(xiàn)target的原因及解決

    文章主要介紹了在使用Maven進(jìn)行項(xiàng)目打包時(shí),`packaging` 屬性的重要性和配置方法,默認(rèn)情況下,Maven會(huì)將項(xiàng)目打包成jar包,如果項(xiàng)目是父級(jí)項(xiàng)目,則`packaging`屬性應(yīng)設(shè)置為`pom`,并通過(guò)`modules`標(biāo)簽引入子項(xiàng)目,這樣可以確保項(xiàng)目的模塊化管理和正確的構(gòu)建順序
    2024-11-11
  • 基于Java回顧之多線程詳解

    基于Java回顧之多線程詳解

    在這篇文章里,我們關(guān)注多線程。多線程是一個(gè)復(fù)雜的話題,包含了很多內(nèi)容,這篇文章主要關(guān)注線程的基本屬性、如何創(chuàng)建線程、線程的狀態(tài)切換以及線程通信,我們把線程同步的話題留到下一篇文章中
    2013-05-05
  • IDEA新建javaWeb以及Servlet簡(jiǎn)單實(shí)現(xiàn)小結(jié)

    IDEA新建javaWeb以及Servlet簡(jiǎn)單實(shí)現(xiàn)小結(jié)

    這篇文章主要介紹了IDEA新建javaWeb以及Servlet簡(jiǎn)單實(shí)現(xiàn)小結(jié),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-11-11
  • Java之JSF框架案例詳解

    Java之JSF框架案例詳解

    這篇文章主要介紹了Java之JSF框架案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • SpringBoot 導(dǎo)出數(shù)據(jù)生成excel文件返回方式

    SpringBoot 導(dǎo)出數(shù)據(jù)生成excel文件返回方式

    這篇文章主要介紹了SpringBoot 導(dǎo)出數(shù)據(jù)生成excel文件返回方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • SpringBoot優(yōu)化接口響應(yīng)時(shí)間的九個(gè)技巧

    SpringBoot優(yōu)化接口響應(yīng)時(shí)間的九個(gè)技巧

    在實(shí)際開(kāi)發(fā)中,提升接口響應(yīng)速度是一件挺重要的事,特別是在面臨大量用戶請(qǐng)求的時(shí)候,本文為大家整理了9個(gè)SpringBoot優(yōu)化接口響應(yīng)時(shí)間的技巧,希望對(duì)大家有所幫助
    2024-01-01
  • Java?數(shù)據(jù)結(jié)構(gòu)進(jìn)階二叉樹(shù)題集下

    Java?數(shù)據(jù)結(jié)構(gòu)進(jìn)階二叉樹(shù)題集下

    二叉樹(shù)可以簡(jiǎn)單理解為對(duì)于一個(gè)節(jié)點(diǎn)來(lái)說(shuō),最多擁有一個(gè)上級(jí)節(jié)點(diǎn),同時(shí)最多具備左右兩個(gè)下級(jí)節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)。本文將帶你通過(guò)實(shí)際題目來(lái)熟練掌握
    2022-04-04

最新評(píng)論