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

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

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

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

問題的提出

編譯運行下面這個程序會看到什么

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);
 }
};

你沒有看錯!結(jié)果確實是

0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999

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

這個問題相當嚴重,如果你有9.999999999999元,你的計算機是不會認為你可以購買10元的商品的。

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

解決方案

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

但是想像一下吧,如果我們要做一個加法運算,需要先將兩個浮點數(shù)轉(zhuǎn)為String,然后夠造成BigDecimal,在其中一個上調(diào)用add方法,傳入另一個作為參數(shù),然后把運算的結(jié)果(BigDecimal)再轉(zhuǎn)換為浮點數(shù)。你能夠忍受這么煩瑣的過程嗎?下面我們提供一個工具類Arith來簡化操作。它提供以下靜態(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的簡單類型不能夠精確的對浮點數(shù)進行運算,這個工具類提供精 確的浮點數(shù)運算,包括加減乘除和四舍五入。
  */
 
 // 默認除法運算精度
 private static final int DEF_DIV_SCALE = 10;
 
 // 這個類不能實例化
 private Arith() {
 }
 
 /**
  * 提供精確的加法運算。
  * 
  * @param v1
  *            被加數(shù)
  * @param v2
  *            加數(shù)
  * @return 兩個參數(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();
 }
 
 /**
  * 提供精確的減法運算。
  * 
  * @param v1
  *            被減數(shù)
  * @param v2
  *            減數(shù)
  * @return 兩個參數(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();
 }
 
 /**
  * 提供精確的乘法運算。
  * 
  * @param v1
  *            被乘數(shù)
  * @param v2
  *            乘數(shù)
  * @return 兩個參數(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();
 }
 
 /**
  * 提供(相對)精確的除法運算,當發(fā)生除不盡的情況時,精確到 小數(shù)點以后10位,以后的數(shù)字四舍五入。
  * 
  * @param v1
  *            被除數(shù)
  * @param v2
  *            除數(shù)
  * @return 兩個參數(shù)的商
  */
 
 public static double div(double v1, double v2) {
  return div(v1, v2, DEF_DIV_SCALE);
 }
 
 /**
  * 提供(相對)精確的除法運算。當發(fā)生除不盡的情況時,由scale參數(shù)指 定精度,以后的數(shù)字四舍五入。
  * 
  * @param v1
  *            被除數(shù)
  * @param v2
  *            除數(shù)
  * @param scale
  *            表示表示需要精確到小數(shù)點以后幾位。
  * @return 兩個參數(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ù)點后保留幾位
  * @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相加時出現(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機制,關(guān)于精度的問題,若是不出現(xiàn)這種情況,保留小數(shù)點后兩位就可以了?;蛘呤褂肂igDecimal進行計算,另外《effective java》這本書里也提過,double和float 不建議使用商業(yè)計算。

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

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

如:2.4的二進制表示并非就是精確的2.4。

反而最為接近的二進制表示是 2.3999999999999999。浮點數(shù)的值實際上是由一個特定的數(shù)學公式計算得到的。

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

相關(guān)文章

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

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

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

    spring boot 枚舉使用的坑整理

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

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

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

    java基礎(chǔ)詳解之數(shù)據(jù)類型知識點總結(jié)

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

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

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

    SpringCloud?Feign超詳細講解

    Feign是Netflix公司開發(fā)的一個聲明式的REST調(diào)用客戶端;?Ribbon負載均衡、?Hystrⅸ服務(wù)熔斷是我們Spring?Cloud中進行微服務(wù)開發(fā)非?;A(chǔ)的組件,在使用的過程中我們也發(fā)現(xiàn)它們一般都是同時出現(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)問題時怎么解決

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

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

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

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

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

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

最新評論

延吉市| 儋州市| 永清县| 勃利县| 盐源县| 杂多县| 西林县| 廊坊市| 长沙市| 潢川县| 乐至县| 砀山县| 博客| 内丘县| 贺州市| 恩施市| 会同县| 吉木萨尔县| 云浮市| 弥勒县| 台东县| 淳化县| 贵阳市| 扶风县| 宜州市| 紫阳县| 杭锦旗| 宁化县| 布尔津县| 临夏市| 万年县| 富川| 海林市| 连江县| 柘城县| 育儿| 鸡泽县| 阿瓦提县| 阿鲁科尔沁旗| 阜阳市| 将乐县|