解决double转 BigDecimal 时出现的精度失真问题
大家好,又见面了,我是你们的朋友全栈君。
比如,
double dd=344999.03d;
转成 BigDecimal 类型,
BigDecimal ss=new BigDecimal(dd);
打印 ss 的值是
344999.03000000002793967723846435546875
精度失真啦!
解决方法是 先将 double 转换 字符串, 然后转换成 BigDecimal 。
代码:
/** * 解决double转bigdecimal时出现的精度问题 * @param v1 * @return */
public static BigDecimal doubleToBig(double v1) {
return new BigDecimal(String.valueOf(v1));
}
查询BigDecimal 源码,得出结论: 所有的 基本数字类型(float、double)转换 BigDecimal 或 BigInteger时,
先将 数字类型 先转成字符串,然后再转换BigDecimal 或 BigInteger。
最后,附上 double转 BigDecimal 的工具类
package com.delongra.nback.system.util;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
/** * 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精 确的浮点数运算,包括加减乘除和四舍五入。 */
public class DoubleUtil {
// 默认除法运算精度
private static final int DEF_DIV_SCALE = 10;
/**#.## */
public static final String REG_1 = "#.##";
/** #,###.## */
public static final String REG_2 = "#,###.##";
// 这个类不能实例化
private DoubleUtil() {
/** * 解决double转bigdecimal时出现的精度问题 * @param v1 * @return */
public static BigDecimal doubleToBig(double v1) {
return new BigDecimal(String.valueOf(v1));
/** * 科学记数法转换成字符串 */
public static String doubleToStr(double v1) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
return b1.toPlainString();
/** * 科学记数法转换成字符串 */
public static String stringToStr(String v1) {
BigDecimal b1 = new BigDecimal(v1);
return b1.toPlainString();
/** * 主要用于格式化金额 * @param v1 * @return */
public static String format(double v1) {
NumberFormat numberFormat = new DecimalFormat(REG_2);
String str = numberFormat.format(v1);
return str;
/** * 主要用于格式化小数点 * @param v1 * @param reg * @return */
public static String format(double v1,String reg) {
NumberFormat numberFormat = new DecimalFormat(reg);
String str = numberFormat.format(v1);
return str;
/** * 加法 */
public static double add(double v1, double ...v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
for (double vv : v2){
BigDecimal b2 = new BigDecimal(Double.toString(vv));
b1=b1.add(b2);
return b1.doubleValue();
/** * 减法 */
public static double sub(double v1, double ...v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
for (double vv : v2){
BigDecimal b2 = new BigDecimal(Double.toString(vv));
b1=b1.subtract(b2);
return b1.doubleValue();
/** * 乘法 */
public static double mul(double v1,double ...v2) {
BigDecimal b1=new BigDecimal(Double.toString(v1));
for (double vv : v2){
BigDecimal b2 = new BigDecimal(Double.toString(vv));
b1=b1.multiply(b2);
return b1.doubleValue();
/** * 除法 */
public static double div(double v1, double ...v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
for (double vv : v2){
BigDecimal b2 = new BigDecimal(Double.toString(vv));
b1=b1.divide(b2, DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP);
return b1.doubleValue();
/** * 小数的四舍五入 */
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();
/** * 两个数比较,获取比较值相对于基准值的大小百分比 * @param base 基准值 * @param compare 比较值 * @return */
public static String getComparePercent(int base,int compare){
if (base==compare) {
return "0%";
if (compare==0) {
return "0%";
if (base==0) {
return compare*100+"%";
NumberFormat numberFormat = NumberFormat.getInstance();