最开始使用了下面这个方法
/**
* 科学计数法读取数字
* 可能导致数据失真
* 如:1.389442444E7
*
* @param d
* @return
*/
@Deprecated
private static String getRealStringValueOfDouble(Double d) {
String doubleStr = d.toString();
boolean b = doubleStr.contains("E");
int indexOfPoint = doubleStr.indexOf('.');
if (b) {
int indexOfE = doubleStr.indexOf('E');
BigInteger xs = new BigInteger(doubleStr.substring(indexOfPoint
+ BigInteger.ONE.intValue(), indexOfE));
int pow = Integer.valueOf(doubleStr.substring(indexOfE
+ BigInteger.ONE.intValue()));
int xsLen = xs.toByteArray().length;
int scale = xsLen - pow > 0 ? xsLen - pow : 0;
doubleStr = String.format("%." + scale + "f", d);
} else {
java.util.regex.Pattern p = Pattern.compile(".0$");
java.util.regex.Matcher m = p.matcher(doubleStr);
if (m.find()) {
doubleStr = doubleStr.replace(".0", "");
}
}
return doubleStr;
}
正如我上面备注的,遇到1.389442444E7这种格式的数据,就会丢失精度,转换为13894424,丢失了小数点后两位
调整后,使用定点数Bigdecimal来转换
/**
* 科学计数法读取数字
*
* @param d
* @return
*/
private static String getDouble2RealString(Double d) {
if (ObjectUtils.isEmpty(d)){
return null;
}
return new BigDecimal(d.toString()).toPlainString();
}
代码上更加简洁了,不过这里也有两个地方需要注意。
- 构建BigDecimal对象时,用String,即将Double准换成String
- 用toPlainString代替toString,这两点一起有效避免了造成精度丢失