概述
问题: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;
}
// Normalize
while ((significand & 1) == 0) { // i.e., significand is even
significand >>= 1;
exponent++;
}
int scale = 0;
// Calculate intVal and scale
BigInteger 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 rounding
int 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丢失精度的坑的全部内容,希望文章能够帮你解决BigDecimal丢失精度的坑所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复