BigDecimal丢失精度的坑
生活随笔
收集整理的這篇文章主要介紹了
BigDecimal丢失精度的坑
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
問題:new BigDecimal(double d)的數值居然還是不精確的
double d = 0.09; BigDecimal bigDecimal=new BigDecimal(d); System.out.println(bigDecimal); System.out.println(d);輸出結果:
0.0899999999999999966693309261245303787291049957275390625
0.09
?
原因:BigDecimal將double數據轉換成為long bits,進行移位計算數值,而double的long bits移位計算是無法得到0.09的精確數值,所有造成數據精度丟失。
為了避免丟失double的數據精度,將double數據轉成String,使用BigDecimal(String s)構造方法。
public class BigDecimal extends Number implements Comparable<BigDecimal>{public BigDecimal(double val) {this(val,MathContext.UNLIMITED);}public BigDecimal(double val, MathContext mc) {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) {this.intVal = BigInteger.ZERO;this.scale = 0;this.intCompact = 0;this.precision = 1;return;}// Normalizewhile ((significand & 1) == 0) { // i.e., significand is evensignificand >>= 1;exponent++;}int scale = 0;// Calculate intVal and scaleBigInteger intVal;long compactVal = sign * significand;if (exponent == 0) {intVal = (compactVal == INFLATED) ? INFLATED_BIGINT : null;} else {if (exponent < 0) {intVal = BigInteger.valueOf(5).pow(-exponent).multiply(compactVal);scale = -exponent;} else { // (exponent > 0)intVal = BigInteger.valueOf(2).pow(exponent).multiply(compactVal);}compactVal = compactValFor(intVal);}int prec = 0;int mcp = mc.precision;if (mcp > 0) { // do roundingint mode = mc.roundingMode.oldMode;int drop;if (compactVal == INFLATED) {prec = bigDigitLength(intVal);drop = prec - mcp;while (drop > 0) {scale = checkScaleNonZero((long) scale - drop);intVal = divideAndRoundByTenPow(intVal, drop, mode);compactVal = compactValFor(intVal);if (compactVal != INFLATED) {break;}prec = bigDigitLength(intVal);drop = prec - mcp;}}if (compactVal != INFLATED) {prec = longDigitLength(compactVal);drop = prec - mcp;while (drop > 0) {scale = checkScaleNonZero((long) scale - drop);compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);prec = longDigitLength(compactVal);drop = prec - mcp;}intVal = null;}}this.intVal = intVal;this.intCompact = compactVal;this.scale = scale;this.precision = prec;} }?
總結
以上是生活随笔為你收集整理的BigDecimal丢失精度的坑的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我终于搞清楚了和String有关的那点事
- 下一篇: 萤火突击国际服怎么下载萤火突击国际服怎么