Java中的高精度計(jì)算怎么利用BigDecimal實(shí)現(xiàn)

本篇文章給大家分享的是有關(guān)Java中的高精度計(jì)算怎么利用BigDecimal實(shí)現(xiàn),小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

創(chuàng)新互聯(lián)是一家專注于成都做網(wǎng)站、成都網(wǎng)站制作與策劃設(shè)計(jì),長海網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)10多年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:長海等地區(qū)。長海做網(wǎng)站價(jià)格咨詢:18980820575

首先看如下代碼示例:

System.out.println(0.05 + 0.01);
System.out.println(0.05 - 0.03);
System.out.println(1.025 * 100);
System.out.println(305.1 / 1000);

輸出結(jié)果為:

0.060000000000000005
0.020000000000000004
102.49999999999999
0.30510000000000004

Java語言支持兩種基本的浮點(diǎn)類型:float和double,以及與它們對應(yīng)的包裝類Float和Double。它們都依據(jù)IEEE 754 標(biāo)準(zhǔn),該標(biāo)準(zhǔn)為 32 位浮點(diǎn)和 64 位雙精度浮點(diǎn)二進(jìn)制小數(shù)定義了二進(jìn)制標(biāo)準(zhǔn)。

IEEE 754 用科學(xué)記數(shù)法以底數(shù)為 2 的小數(shù)來表示浮點(diǎn)數(shù)。IEEE 浮點(diǎn)數(shù)用 1 位表示數(shù)字的符號,用 8 位來表示指數(shù),用 23 位來表示尾數(shù),即小數(shù)部分,作為有符號整數(shù)的指數(shù)可以有正負(fù)之分,小數(shù)部分用二進(jìn)制(底數(shù) 2)小數(shù)來表示

不要用浮點(diǎn)值表示精確值

一些非整數(shù)值(如幾美元和幾美分這樣的小數(shù))需要很精確。浮點(diǎn)數(shù)不是精確值,所以使用它們會導(dǎo)致舍入誤差。因此,使用浮點(diǎn)數(shù)來試圖表示象貨幣量這樣的精確數(shù)量不是一個(gè)好的想法。使用浮點(diǎn)數(shù)來進(jìn)行美元和美分計(jì)算會得到災(zāi)難性的后果。浮點(diǎn)數(shù)最好用來表示象測量值這類數(shù)值,這類值從一開始就不怎么精確。

使用BigDecimal

從 JDK 1.3 起,Java 開發(fā)人員就有了另一種數(shù)值表示法來表示非整數(shù): BigDecimal 。 BigDecimal 是標(biāo)準(zhǔn)的類,在編譯器中不需要特殊支持,它可以表示任意精度的小數(shù),并對它們進(jìn)行計(jì)算。

用于加、減、乘和除的方法給 BigDecimal 值提供了算術(shù)運(yùn)算。由于 BigDecimal 對象是不可變的,這些方法中的每一個(gè)都會產(chǎn)生新的 BigDecimal 對象。因此,因?yàn)閯?chuàng)建對象的開銷, BigDecimal 不適合于大量的數(shù)學(xué)計(jì)算,但設(shè)計(jì)它的目的是用來精確地表示小數(shù)。如果您正在尋找一種能精確表示如貨幣量這樣的數(shù)值,則 BigDecimal 可以很好地勝任該任務(wù)。

構(gòu)造 BigDecimal 數(shù)

對于 BigDecimal ,有幾個(gè)可用的構(gòu)造函數(shù)。其中一個(gè)構(gòu)造函數(shù)以雙精度浮點(diǎn)數(shù)作為輸入,另一個(gè)以整數(shù)和換算因子作為輸入,還有一個(gè)以小數(shù)的 String 表示作為輸入。要小心使用 BigDecimal(double) 構(gòu)造函數(shù),因?yàn)槿绻涣私馑瑫谟?jì)算過程中產(chǎn)生舍入誤差。請使用基于整數(shù)或 String 的構(gòu)造函數(shù)。

public class Test {
  public static void main(String[] args) {
    // 以雙精度浮點(diǎn)數(shù)進(jìn)行構(gòu)造
    BigDecimal bd1 = new BigDecimal(0.5);
    BigDecimal bd2 = new BigDecimal(0.1);
    System.out.println(bd1.add(bd2));

    // 以String類型進(jìn)行構(gòu)造
    BigDecimal bd3 = new BigDecimal("0.5");
    BigDecimal bd4 = new BigDecimal("0.1");
    System.out.println(bd3.add(bd4));
  }
}

輸出結(jié)果為:

0.6000000000000000055511151231257827021181583404541015625
0.6

上面代碼分別以

BigDecimal(double val)
BigDecimal(String val)

不同的方式進(jìn)行構(gòu)造 BigDecimal 數(shù),輸出的結(jié)果是不一樣的。

回到最開始的示例,提供工具類進(jìn)行精確的浮點(diǎn)數(shù)運(yùn)算,包括加減乘除和四舍五入。

import java.math.BigDecimal;

public class ArithUtil {
  private static final int DEF_DIV_SCALE = 6; // 默認(rèn)除法運(yùn)算精度

  /**
   * 提供精確的加法運(yùn)算。
   *
   * @param v1 被加數(shù)
   * @param v2 加數(shù)
   * @return 兩個(gè)參數(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();
  }

  /**
   * 提供精確的減法運(yùn)算。
   *
   * @param v1 被減數(shù)
   * @param v2 減數(shù)
   * @return 兩個(gè)參數(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();
  }

  /**
   * 提供精確的乘法運(yùn)算。
   *
   * @param v1 被乘數(shù)
   * @param v2 乘數(shù)
   * @return 兩個(gè)參數(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();
  }

  /**
   * 提供(相對)精確的除法運(yùn)算,當(dāng)發(fā)生除不盡的情況時(shí),精確到 小數(shù)點(diǎn)以后10位,以后的數(shù)字四舍五入。
   *
   * @param v1 被除數(shù)
   * @param v2 除數(shù)
   * @return 兩個(gè)參數(shù)的商
   */
  public static double div(double v1, double v2) {
    return div(v1, v2, DEF_DIV_SCALE);
  }

  /**
   * 提供(相對)精確的除法運(yùn)算。當(dāng)發(fā)生除不盡的情況時(shí),由scale參數(shù)指 定精度,以后的數(shù)字四舍五入。
   *
   * @param v1 被除數(shù)
   * @param v2 除數(shù)
   * @param scale 表示表示需要精確到小數(shù)點(diǎn)以后幾位。
   * @return 兩個(gè)參數(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();
  }

  /**
   * 提供精確的小數(shù)位四舍五入處理。
   *
   * @param v 需要四舍五入的數(shù)字
   * @param scale 小數(shù)點(diǎn)后保留幾位
   * @return 四舍五入后的結(jié)果
   */
  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));
    BigDecimal one = new BigDecimal("1");

    return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
  }
}

結(jié)束語:

在 Java 程序中使用浮點(diǎn)數(shù)和小數(shù)充滿著陷阱。浮點(diǎn)數(shù)和小數(shù)不象整數(shù)一樣“循規(guī)蹈矩”,不能假定浮點(diǎn)計(jì)算一定產(chǎn)生整型或精確的結(jié)果,雖然它們的確“應(yīng)該”那樣做。最好將浮點(diǎn)運(yùn)算保留用作計(jì)算本來就不精確的數(shù)值,譬如測量。如果需要表示定點(diǎn)數(shù)(譬如,幾美元和幾美分),則使用 BigDecimal 。

以上就是Java中的高精度計(jì)算怎么利用BigDecimal實(shí)現(xiàn),小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿姷交蛴玫降摹OM隳芡ㄟ^這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

當(dāng)前題目:Java中的高精度計(jì)算怎么利用BigDecimal實(shí)現(xiàn)
網(wǎng)頁鏈接:http://bm7419.com/article8/iioiop.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站、網(wǎng)站設(shè)計(jì)公司、服務(wù)器托管、建站公司、軟件開發(fā)、小程序開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)