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

聊聊Java Double相加出現(xiàn)的怪事

 更新時(shí)間:2021年12月13日 08:57:41   作者:lanyan_lan  
這篇文章主要介紹了Java Double相加出現(xiàn)的怪事,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Java Double相加出現(xiàn)的怪事

問題的提出

編譯運(yùn)行下面這個(gè)程序會(huì)看到什么

public class test {
 public static void main(String args[]) {
  System.out.println(0.05 + 0.01);
  System.out.println(1.0 - 0.42);
  System.out.println(4.015 * 100);
  System.out.println(123.3 / 100);
 }
};

你沒有看錯(cuò)!結(jié)果確實(shí)是

0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999

Java中的簡(jiǎn)單浮點(diǎn)數(shù)類型float和double不能夠進(jìn)行運(yùn)算。不光是Java,在其它很多編程語言中也有這樣的問題。在大多數(shù)情況下,計(jì)算的結(jié)果是準(zhǔn)確的,但是多試幾次(可以做一個(gè)循環(huán))就可以試出類似上面的錯(cuò)誤?,F(xiàn)在終于理解為什么要有BCD碼了。

這個(gè)問題相當(dāng)嚴(yán)重,如果你有9.999999999999元,你的計(jì)算機(jī)是不會(huì)認(rèn)為你可以購(gòu)買10元的商品的。

在有的編程語言中提供了專門的貨幣類型來處理這種情況,但是Java沒有?,F(xiàn)在讓我們看看如何解決這個(gè)問題。

解決方案

現(xiàn)在我們已經(jīng)可以解決這個(gè)問題了,原則是使用BigDecimal并且一定要用String來夠造。

但是想像一下吧,如果我們要做一個(gè)加法運(yùn)算,需要先將兩個(gè)浮點(diǎn)數(shù)轉(zhuǎn)為String,然后夠造成BigDecimal,在其中一個(gè)上調(diào)用add方法,傳入另一個(gè)作為參數(shù),然后把運(yùn)算的結(jié)果(BigDecimal)再轉(zhuǎn)換為浮點(diǎn)數(shù)。你能夠忍受這么煩瑣的過程嗎?下面我們提供一個(gè)工具類Arith來簡(jiǎn)化操作。它提供以下靜態(tài)方法,包括加減乘除和四舍五入:

public static double add(double v1, double v2); 
 public static double sub(double v1, double v2); 
 public static double mul(double v1, double v2); 
 public static double div(double v1, double v2); 
 public static double div(double v1, double v2, int scale); 
 public static double round(double v, int scale);
package org.nutz.mvc.core; 
import java.math.BigDecimal; 
public class Arith {
 // 源文件Arith.java:
 
 /**
  * 由于Java的簡(jiǎn)單類型不能夠精確的對(duì)浮點(diǎn)數(shù)進(jìn)行運(yùn)算,這個(gè)工具類提供精 確的浮點(diǎn)數(shù)運(yùn)算,包括加減乘除和四舍五入。
  */
 
 // 默認(rèn)除法運(yùn)算精度
 private static final int DEF_DIV_SCALE = 10;
 
 // 這個(gè)類不能實(shí)例化
 private Arith() {
 }
 
 /**
  * 提供精確的加法運(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();
 }
 
 /**
  * 提供(相對(duì))精確的除法運(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);
 }
 
 /**
  * 提供(相對(duì))精確的除法運(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();
 }
};

Double相加時(shí)出現(xiàn)的多位問題

String test = "40.61 ,  18588.73,    29925.07,    7986.06,    18639.19,    25914.32,     32907.74,     34165.89,     9724.7,     52777.92";
 String[] arr = test.split(",");
 double sum = 0;
 for(int i=0;i<arr.length;i++){
 sum += Double.parseDouble(arr[i]);
 }
     System.out.println(sum); 

結(jié)果: 230670.22999999998

查了查 沒有深入的了解,大概是java 的double機(jī)制,關(guān)于精度的問題,若是不出現(xiàn)這種情況,保留小數(shù)點(diǎn)后兩位就可以了?;蛘呤褂肂igDecimal進(jìn)行計(jì)算,另外《effective java》這本書里也提過,double和float 不建議使用商業(yè)計(jì)算。

補(bǔ)充:原因在于我們的計(jì)算機(jī)是二進(jìn)制的。浮點(diǎn)數(shù)沒有辦法是用二進(jìn)制進(jìn)行精確表示。

我們的CPU表示浮點(diǎn)數(shù)由兩個(gè)部分組成:指數(shù)和尾數(shù),這樣的表示方法一般都會(huì)失去一定的精確度,有些浮點(diǎn)數(shù)運(yùn)算也會(huì)產(chǎn)生一定的誤差。

如:2.4的二進(jìn)制表示并非就是精確的2.4。

反而最為接近的二進(jìn)制表示是 2.3999999999999999。浮點(diǎn)數(shù)的值實(shí)際上是由一個(gè)特定的數(shù)學(xué)公式計(jì)算得到的。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java?安全ysoserial?URLDNS利用鏈分析

    java?安全ysoserial?URLDNS利用鏈分析

    這篇文章主要為大家介紹了java?安全ysoserial?URLDNS利用鏈分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • spring boot 枚舉使用的坑整理

    spring boot 枚舉使用的坑整理

    在本篇文章里我們給大家整理了關(guān)于spring boot 枚舉使用的坑以及相關(guān)知識(shí)點(diǎn)內(nèi)容,需要的朋友們學(xué)習(xí)下。
    2019-08-08
  • Java類之間的關(guān)系圖_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java類之間的關(guān)系圖_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    在Java以及其他的面向?qū)ο笤O(shè)計(jì)模式中,類與類之間主要有6種關(guān)系,他們分別是:依賴、關(guān)聯(lián)、聚合、組合、繼承、實(shí)現(xiàn)。他們的耦合度依次增強(qiáng),有興趣的可以了解一下
    2017-08-08
  • java基礎(chǔ)詳解之?dāng)?shù)據(jù)類型知識(shí)點(diǎn)總結(jié)

    java基礎(chǔ)詳解之?dāng)?shù)據(jù)類型知識(shí)點(diǎn)總結(jié)

    這篇文章主要介紹了java基礎(chǔ)詳解之?dāng)?shù)據(jù)類型知識(shí)點(diǎn)總結(jié),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有很大的幫助,需要的朋友可以參考下
    2021-04-04
  • Java中的值傳遞和引用傳遞區(qū)別解析

    Java中的值傳遞和引用傳遞區(qū)別解析

    這篇文章主要介紹了Java中的值傳遞和引用傳遞區(qū)別解析,引用類型的變量保存引用值,“引用值”指向內(nèi)存空間的地址,代表了某個(gè)對(duì)象的引用,而不是對(duì)象本身,對(duì)象本身存放在該引用值所表示的地址的位置,包含:數(shù)組、類、接口,需要的朋友可以參考下
    2023-11-11
  • SpringCloud?Feign超詳細(xì)講解

    SpringCloud?Feign超詳細(xì)講解

    Feign是Netflix公司開發(fā)的一個(gè)聲明式的REST調(diào)用客戶端;?Ribbon負(fù)載均衡、?Hystrⅸ服務(wù)熔斷是我們Spring?Cloud中進(jìn)行微服務(wù)開發(fā)非?;A(chǔ)的組件,在使用的過程中我們也發(fā)現(xiàn)它們一般都是同時(shí)出現(xiàn)的,而且配置也都非常相似
    2022-10-10
  • 并發(fā)編程之Java內(nèi)存模型鎖的內(nèi)存語義

    并發(fā)編程之Java內(nèi)存模型鎖的內(nèi)存語義

    這篇文章主要介紹了并發(fā)編程之Java內(nèi)存模型鎖的內(nèi)存語義,鎖的作用是讓臨界區(qū)互斥執(zhí)行,本文只要圍繞鎖的內(nèi)存語義展開全文內(nèi)容,需要的小伙伴可以參考一下
    2021-11-11
  • 在win10系統(tǒng)下,如何配置Spring Cloud alibaba Seata以及出現(xiàn)問題時(shí)怎么解決

    在win10系統(tǒng)下,如何配置Spring Cloud alibaba Seata以及出現(xiàn)問題時(shí)怎么解決

    今天教大家如何在win10系統(tǒng)下,配置Spring Cloud alibaba Seata以及出現(xiàn)問題時(shí)怎么解決,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 關(guān)于jdk環(huán)境變量的配置方式解讀

    關(guān)于jdk環(huán)境變量的配置方式解讀

    這篇文章主要介紹了關(guān)于jdk環(huán)境變量的配置方式解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • 詳解OpenAPI開發(fā)如何動(dòng)態(tài)的添加接口實(shí)現(xiàn)

    詳解OpenAPI開發(fā)如何動(dòng)態(tài)的添加接口實(shí)現(xiàn)

    這篇文章主要為大家介紹了OpenAPI開發(fā)如何動(dòng)態(tài)的添加接口實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04

最新評(píng)論

平乡县| 石景山区| 大邑县| 成安县| 阿拉善盟| 东海县| 汪清县| 青阳县| 永平县| 保康县| 恩平市| 固镇县| 松江区| 大宁县| 盐池县| 富顺县| 凤台县| 卓尼县| 会理县| 湖口县| 黄浦区| 潞城市| 综艺| 巫溪县| 莆田市| 武山县| 和田市| 桐城市| 安多县| 桦甸市| 织金县| 南通市| 荔浦县| 南开区| 桐城市| 汕尾市| 陈巴尔虎旗| 金华市| 大竹县| 扎兰屯市| 濮阳市|