理论
金额是小数,而且必须精确,所以用BigDecimal。
所以,金融场景一般用BigDecimal。非金融场景,一般用double就够了,因为不要求那么精确,而且可以少占一点空间,计算速度也会快一点。
工作使用
公司ys,金额和手续费都是Double。加减的时候,没有精度问题吗?有,但是底层通过BigDecimal转换了一下精度,本质是四舍五入了,所以就没有精度的问题。
公司zf,全部都是BigDecimal。
double有什么问题?
有精度问题。
测试代码
import java.math.BigDecimal;
import lombok.extern.slf4j.Slf4j;
/**
* 测试double的精度问题
*
* @author gzh
* @createTime 2021/10/6 10:55 AM
*/
@Slf4j
public class TestDouble {
public static void main(String[] args) {
// double d1 = 0.03;
// double d2 = 0.02;
// double d3 = d1 -d2;
// log.info(String.valueOf(d3)); //0.009999999999999998
//
// Double d1 = 0.03;
// Double d2 = 0.02;
// Double d3 = d1 -d2;
// log.info(String.valueOf(d3)); //0.009999999999999998
// log.info(String.valueOf(subtract(d1,d2))); //0.01,因为底层用BigDecimal转换了一下精度,公司ys就是这么玩的。
BigDecimal d1 = BigDecimal.valueOf(0.03);
BigDecimal d2 = BigDecimal.valueOf(0.02);
BigDecimal d3 = d1.subtract(d2);
log.info(String.valueOf(d3)); //0.01
}
/**
* 减法
*
* @author gzh
* @date 2021/10/6 12:47 PM
* @param d1
* @param d2
* @return java.lang.Double
*/
public static Double subtract(Double d1, Double d2)
{
return new Double(format(d1.doubleValue() - d2.doubleValue()));
}
/**
* 用BigDecimal转换double精度。
* 为什么BigDecimal精度准确,double不准确?因为BigDecimal四舍五入了。
*
* @author gzh
* @date 2021/10/6 12:47 PM
* @param value
* @return double
*/
public static double format(double value)
{
return new BigDecimal(Double.toString(value)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
数据库
数据库oracle、mysql都有decimal类型,所以代码层面和数据库层面都统一用同一个数据类型。
注:如果用的是double,代码层面和数据库层面也要统一用double。
BigDecimal和double的区别?
为什么double就有精度问题?而BigDecimal就没有精度问题?BigDecimal是怎么解决精度的?因为本质是BigDecimal进行四舍五入了。
并且,BigDecimal数据长度可以无限大。
最佳实践
用BigDecimal,因为涉及到金额的问题,肯定数据准确是第一重要的,至于多占了一点点空间,速度慢一点点,都不是最重要的。
参考
《java核心技术》