2026/2/13 2:16:55
网站建设
项目流程
网站建设 6万元,外贸英语学习网站,成品网站软件大全下载,成都软件开发公司排行榜我们都知道在计算钱的时候首选 BigDecimal#xff0c;因为它不会导致丢失精度的情况#xff0c;尤其在金融领域#xff0c;为了保证数据的精度#xff0c;往往都会使用BigDecimal。本文就来探讨下为什么BigDecimal可以保证精度不丢失。类介绍首先来看一下BigDecimal的类声明…我们都知道在计算钱的时候首选 BigDecimal因为它不会导致丢失精度的情况尤其在金融领域为了保证数据的精度往往都会使用BigDecimal。本文就来探讨下为什么BigDecimal可以保证精度不丢失。类介绍首先来看一下BigDecimal的类声明以及几个属性public class BigDecimal extends Number implements ComparableBigDecimal { // 该BigDecimal的未缩放值 private final BigInteger intVal; // 精度可以理解成小数点后的位数 private final int scale; // BigDecimal中的十进制位数如果位数未知则为0(备用信息) private transient int precision; // Used to store the canonical string representation, if computed. // 这个我理解就是存实际的BigDecimal值 private transient String stringCache; // 扩大成long型数值后的值 private final transient long intCompact; }从例子入手通过debug来发现源码中的奥秘是了解类运行机制很好的方式。请看下面的testBigDecimal方法Test public void testBigDecimal() { BigDecimal bigDecimal1 BigDecimal.valueOf(2.36); BigDecimal bigDecimal2 BigDecimal.valueOf(3.5); BigDecimal resDecimal bigDecimal1.add(bigDecimal2); System.out.println(resDecimal); }在执行了BigDecimal.valueOf(2.36)后查看debug信息可以发现上述提到的几个属性被赋了值图片接下来进到add方法里面看看它是怎么计算的/** * Returns a BigDecimal whose value is (this augend), * and whose scale is max(this.scale(), augend.scale()). */ public BigDecimal add(BigDecimal augend) { if (this.intCompact ! INFLATED) { if ((augend.intCompact ! INFLATED)) { return add(this.intCompact, this.scale, augend.intCompact, augend.scale); } else { return add(this.intCompact, this.scale, augend.intVal, augend.scale); } } else { if ((augend.intCompact ! INFLATED)) { return add(augend.intCompact, augend.scale, this.intVal, this.scale); } else { return add(this.intVal, this.scale, augend.intVal, augend.scale); } } }看一下传进来的值图片进入第8行的add方法private static BigDecimal add(final long xs, int scale1, final long ys, int scale2) { long sdiff (long) scale1 - scale2; if (sdiff 0) { return add(xs, ys, scale1); } else if (sdiff 0) { int raise checkScale(xs,-sdiff); long scaledX longMultiplyPowerTen(xs, raise); if (scaledX ! INFLATED) { return add(scaledX, ys, scale2); } else { BigInteger bigsum bigMultiplyPowerTen(xs,raise).add(ys); return ((xs^ys)0) ? // same sign test new BigDecimal(bigsum, INFLATED, scale2, 0) : valueOf(bigsum, scale2, 0); } } else { int raise checkScale(ys,sdiff); long scaledY longMultiplyPowerTen(ys, raise); if (scaledY ! INFLATED) { return add(xs, scaledY, scale1); } else { BigInteger bigsum bigMultiplyPowerTen(ys,raise).add(xs); return ((xs^ys)0) ? new BigDecimal(bigsum, INFLATED, scale1, 0) : valueOf(bigsum, scale1, 0); } } }这个例子中该方法传入的参数分别是xs236scale12ys35scale21该方法首先计算scale1 - scale2根据差值走不同的计算逻辑这里求出来是1所以进入到最下面的else代码块这块是关键首先17行校验了一下数值范围18行将ys扩大了10的n次倍这里nraise1所以返回的scaledY350接着就进入到20行的add方法private static BigDecimal add(long xs, long ys, int scale){ long sum add(xs, ys); if (sum!INFLATED) return BigDecimal.valueOf(sum, scale); return new BigDecimal(BigInteger.valueOf(xs).add(ys), scale); }这个方法很简单就是计算和然后返回BigDecimal对象结论所以可以得出结论BigDecimal在计算时实际会把数值扩大10的n次倍变成一个long型整数进行计算整数计算时自然可以实现精度不丢失。同时结合精度scale实现最终结果的计算。