当前位置: 首页 > news >正文

一算钱领导就让用BigDecimal ,为什么它可以不丢失精度?

我们都知道在计算钱的时候首选 BigDecimal,因为它不会导致丢失精度的情况,尤其在金融领域,为了保证数据的精度,往往都会使用BigDecimal。本文就来探讨下为什么BigDecimal可以保证精度不丢失。

类介绍

首先来看一下BigDecimal的类声明以及几个属性:

public class BigDecimal extends Number implements Comparable<BigDecimal> { // 该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); } } }

这个例子中,该方法传入的参数分别是:xs=236,scale1=2,ys=35,scale2=1

该方法首先计算scale1 - scale2,根据差值走不同的计算逻辑,这里求出来是1,所以进入到最下面的else代码块(这块是关键):

  • 首先17行校验了一下数值范围

  • 18行将ys扩大了10的n次倍,这里n=raise=1,所以返回的scaledY=350

  • 接着就进入到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,实现最终结果的计算。

http://www.jsqmd.com/news/217036/

相关文章:

  • 用这套新工作流,把上线时间从半天压到3分钟
  • 删除链表的倒数第n个节点
  • 【毕业设计】机器学习 基于python深度学习的猫狗表情识别
  • 6784358
  • 【疾病识别】SVM农作物叶子虫害识别与分类【含GUI Matlab源码 14872期】
  • 两个链表的第一个公共结点
  • 深度学习毕设项目:基于CNN深度学习python的遥感图片识别沙漠湖泊和森林
  • 用这4招,优雅的实现Spring Boot 异步线程间数据传递
  • 【课程设计/毕业设计】基于python机器学习的猫狗表情识别
  • 【建议收藏】AI 音乐提示词终极指南|全网最全的创作控制手册|Suno 进阶指南|第 15 篇
  • 链表相加(二)
  • 深度学习毕设项目:基于python的印刷体数字和字母识别基于python深度学习的印刷体数字和字母识别
  • 在RabbitMQ中,怎么确保消息不会丢失?
  • 从一道前端面试题,谈 JS 对象存储特点和运算符执行顺序
  • 大数据领域Zookeeper的集群配置自动化工具推荐
  • 【交通标示识别】模板匹配雾霾交通标示识别【含GUI Matlab源码 14873期】
  • MYSQL_安装与配置(超详细,仅需一篇就能帮你成功安装MYSQL)
  • PO、VO、BO、DTO、DAO、POJO有什么区别?
  • ArcGIS Pro3.5.2安装包+安装详细教程+系统需求
  • MySQL进程CPU 飙升900%,领导让我查什么原因?
  • 【课程设计/毕业设计】基于 python的CNN深度学习的遥感图片识别沙漠湖泊和森林
  • ArcGIS Pro查看多期数据变化!卷帘+多地图联动齐上架
  • Stream流式编程 中间操作和终端操作介绍
  • 【苹果分级】基于matlab GUI机器视觉苹果质量检测及总分级系统【含Matlab源码 14878期】
  • 【课程设计/毕业设计】基于深度学习的印刷体数字和字母识别基于python深度学习的印刷体数字和字母识别
  • 深度学习计算机毕设之机器学习基于CNN深度学习的遥感图片识别沙漠湖泊和森林
  • ArcGIS土地利用现状图制作全流程
  • Merge3D 三维引擎中 GeoJSON 数据加载的整体设计
  • K8S安装指南与核心操作命令汇总
  • 企业知识管理新范式:用ChatWiki+大模型实现“一问即答“[必学收藏]