Java學(xué)習(xí)筆記:關(guān)于Java?double類型相加問題
Java double類型相加問題
多個(gè)double類型的數(shù)直接相加的時(shí)候,可能存在精度誤差.( 由于計(jì)算機(jī)算法以及硬件環(huán)境決定只能識(shí)別 0 1。計(jì)算機(jī)默認(rèn)的計(jì)算結(jié)果在都在一個(gè)指定精度范圍之內(nèi),想往深的了解,可以學(xué)習(xí)數(shù)值分析等)
在金融方面是絕對(duì)不允許的,好在java開發(fā)者有這個(gè)先見之明。
java.math.*里面提供了BigDecimal類(提供高精度計(jì)算的方法)
一、這個(gè)時(shí)候就要采用BigDecimal函數(shù)進(jìn)行運(yùn)算
第一步、建立String類型的數(shù)據(jù)
第二步、創(chuàng)建BigDecimal對(duì)象BigDecimal(Double.toString(double))
以下兩種不推薦:
BigDecimal(double)或者BigDecimal(Double.valueOf(double)))
建議: 涉及到精度問題的時(shí)候,整個(gè)計(jì)算過程都是用String類型或者BigDecimal類對(duì)象。最后結(jié)果根據(jù)需求 在轉(zhuǎn)過來。
另外該文章提供了一個(gè)計(jì)算輔助類Java Double相加出現(xiàn)的怪事
急需的話,直接學(xué)習(xí)、創(chuàng)建該工具類,就可以完成項(xiàng)目了。以下是 加法算法的幾個(gè)實(shí)現(xiàn)的方法。
new BigDecimal(Double.toString(double)).add(new BigDecimal(Double.toString(double));
/** * @param b1 * BigDecimal * @param v2 * double * @return BigDecimal * */ public BigDecimal add(BigDecimal b1, double v2) { // BigDecimal b1=new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2); }
/** * @param b1 * double * @param v2 * double * @return BigDecimal * */ public BigDecimal add(double v1, double v2) { BigDecimal b1=new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2); }
/** * @param b1 * double * @param v2 * double * @return double * */ public 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(); }
二、double 三種加法比較
+,strictfp,BigDecimel
Strictfp —— Java 關(guān)鍵字。
可應(yīng)用于類、接口或方法。
使用 strictfp 關(guān)鍵字聲明一個(gè)方法時(shí),該方法中所有的float和double表達(dá)式都嚴(yán)格遵守FP-strict的限制,符合IEEE-754規(guī)范。
嚴(yán)格約束意味著所有表達(dá)式的結(jié)果都必須是 IEEE 754 算法對(duì)操作數(shù)預(yù)期的結(jié)果,以單精度和雙精度格式表示。
public class MathDemo { /** * @param args */ public static void main(String[] args) { System.err.println("普通 "+ addNormal(12353.21,21334.24,154435.03)); System.err.println("strictfp "+addDouble(12353.21,21334.24,154435.03)); System.err.println("BigDEcimel: "+add(12353.21,21334.24,154435.03)); } public static double addNormal(double... v1) { double res = 0; for (int i = 0; i < v1.length; i++) { res += v1[i]; } return res; } public static strictfp double addDouble(double... v) { double res = 0; for (int i = 0; i < v.length; i++) { res += v[i]; } return res; } /** * @param b1 * double * @param v2 * double * @return double */ public static double add(double... v) { BigDecimal b = new BigDecimal(Double.toString(v[0])); for (int i = 1; i < v.length; i++) { BigDecimal b2 = new BigDecimal(Double.toString(v[i])); b=b.add(b2); } return b.doubleValue(); } }
輸入
12353.21,21334.24,154435.03三個(gè)類型的數(shù)據(jù)時(shí)候
結(jié)果:
普通 188122.47999999998
strictfp 188122.47999999998
BigDEcimel: 188122.48輸入
3.21, 4.24,5.03
結(jié)果
普通 12.48
strictfp 12.48
BigDEcimel: 12.48輸入:
12353.21,21334.24
結(jié)果:
普通 33687.45
strictfp 33687.45
BigDEcimel: 33687.45
結(jié)論是:
BigDecimal的算法精度比較好。 其余兩種方法 都存在缺點(diǎn)。至于strictfp 這個(gè)關(guān)鍵字 是去平臺(tái)化影響。比如32為機(jī)器和64位機(jī)器結(jié)果都一樣。 對(duì)于精度計(jì)算結(jié)果影響不大。
附錄:.
//使用double類型創(chuàng)建BigDecimal public BigDecimal(double val) { if (Double.isInfinite(val) || Double.isNaN(val)) throw new NumberFormatException("Infinite or NaN"); // Translate the double into sign, exponent and significand, according // to the formulae in JLS, Section 20.10.22. long valBits = Double.doubleToLongBits(val); int sign = ((valBits >> 63)==0 ? 1 : -1); int exponent = (int) ((valBits >> 52) & 0x7ffL); long significand = (exponent==0 ? (valBits & ((1L<<52) - 1)) << 1 : (valBits & ((1L<<52) - 1)) | (1L<<52)); exponent -= 1075; // At this point, val == sign * significand * 2**exponent. /* * Special case zero to supress nonterminating normalization * and bogus scale calculation. */ if (significand == 0) { intVal = BigInteger.ZERO; intCompact = 0; precision = 1; return; } // Normalize while((significand & 1) == 0) { // i.e., significand is even significand >>= 1; exponent++; } // Calculate intVal and scale long s = sign * significand; BigInteger b; if (exponent < 0) { b = BigInteger.valueOf(5).pow(-exponent).multiply(s); scale = -exponent; } else if (exponent > 0) { b = BigInteger.valueOf(2).pow(exponent).multiply(s); } else { b = BigInteger.valueOf(s); } intCompact = compactValFor(b); intVal = (intCompact != INFLATED) ? null : b; }
Java double類詳解
Double 類的構(gòu)造方法
Double 類中的構(gòu)造方法有如下兩個(gè)。
Double(double value)
:構(gòu)造一個(gè)新分配的 Double 對(duì)象,它表示轉(zhuǎn)換為 double 類型的參數(shù)。
Double(String s)
:構(gòu)造一個(gè)新分配的 Double 對(duì)象,它表示 String 參數(shù)所指示的 double 值。
分別使用以上兩個(gè)構(gòu)造方法獲取 Double 對(duì)象:
Double double1 = new Double(5.556); // 以 double 類型的變量作為參數(shù)創(chuàng)建 Double 對(duì)象 Double double2 = new Double("5.486"); // 以 String 類型的變量作為參數(shù)創(chuàng)建 Double 對(duì)象
Double 類的常用方法
如何將字符串 56.7809 轉(zhuǎn)換為 double 類型的數(shù)值,或者將 double 類型的數(shù)值 56.7809 轉(zhuǎn)換為對(duì)應(yīng)的字符串呢?
String str = "56.7809"; double num = Double.parseDouble(str); // 將字符串轉(zhuǎn)換為 double 類型的數(shù)值 double d = 56.7809; String s = Double.toString(d); // 將double類型的數(shù)值轉(zhuǎn)換為字符串
在將字符串轉(zhuǎn)換為 double 類型的數(shù)值的過程中,如果字符串中包含非數(shù)值類型的字符,則程序執(zhí)行將出現(xiàn)異常。
Double 類的常用常量
在 Double 類中包含了很多常量,其中較為常用的常量如下。
MAX_VALUE
:值為 1.8E308 的常量,它表示 double 類型的最大正有限值的常量。MIN_VALUE
:值為 4.9E-324 的常量,它表示 double 類型數(shù)據(jù)能夠保持的最小正非零值的常量。NaN
:保存 double 類型的非數(shù)字值的常量。NEGATIVE_INFINITY
:保持 double 類型的負(fù)無窮大的常量。POSITIVE_INFINITY
:保持 double 類型的正無窮大的常量。SIZE
:用秦以二進(jìn)制補(bǔ)碼形式表示 double 值的比特位數(shù)。TYPE
:表示基本類型 double 的 Class 實(shí)例。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java http token請(qǐng)求代碼實(shí)例
這篇文章主要介紹了java http token請(qǐng)求,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03如何優(yōu)雅的拋出Spring Boot注解的異常詳解
這篇文章主要給大家介紹了關(guān)于如何優(yōu)雅的拋出Spring Boot注解的異常的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12Java中如何對(duì)字符串進(jìn)行utf-8編碼
這篇文章主要介紹了Java中如何對(duì)字符串進(jìn)行utf-8編碼問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04Netty源碼分析NioEventLoop線程的啟動(dòng)
這篇文章主要為大家介紹了Netty源碼分析NioEventLoop線程的啟動(dòng)示例,有需要的朋友,可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03SpringBoot thymeleaf eclipse熱部署方案操作步驟
今天小編就為大家分享一篇關(guān)于SpringBoot thymeleaf eclipse熱部署方案操作步驟,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03詳細(xì)分析Java并發(fā)集合LinkedBlockingQueue的用法
這篇文章主要介紹了詳細(xì)分析Java并發(fā)集合LinkedBlockingQueue的用法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04