一算钱领导就让用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.mzph.cn/news/1131493.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用这套新工作流,把上线时间从半天压到3分钟

“在我电脑上明明是好的”&#xff0c;这句话我曾说过无数次&#xff0c;也听过无数次。每次上线前&#xff0c;我们团队都要花大量时间在联调和解决各种诡异的环境问题上。我开始反思&#xff1a;我们真正的问题&#xff0c;或许根本不是代码&#xff0c;而是那个看不见、摸不…

【毕业设计】机器学习 基于python深度学习的猫狗表情识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

GB/T 24137-2009 木塑装饰板检测

木塑装饰板是指室内外装饰用非结构型木塑复合板材。主要有墙板、壁板和天花等&#xff1b;以木塑复合板为基材经涂饰或以各种装饰材料饰面而成的板材称作饰面木塑装饰板。GB/T 24137-2009木塑装饰板检测介绍测试要求测试标准外观GB/T 24137长度,宽度,厚度尺寸GB/T 19367.1边缘直…

【毕业设计】机器学习基于cnn识别微小细胞细菌细胞器

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

【疾病识别】SVM农作物叶子虫害识别与分类【含GUI Matlab源码 14872期】

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;Matlab武动乾坤博客之家&#x1f49e;…

两个链表的第一个公共结点

求解代码 public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {// 初始化两个临时指针&#xff0c;分别指向两个链表的头节点ListNode temp1 pHead1;ListNode temp2 pHead2;// 只要两个指针不指向同一个节点&#xff0c;就继续遍历while (temp1 ! temp2…

用这4招,优雅的实现Spring Boot 异步线程间数据传递

Spring Boot 自定义线程池可以实现异步开发&#xff0c;在实际开发中需要在父子线程之间传递一些数据&#xff0c;比如用户信息&#xff0c;链路信息等等比如用户登录信息使用ThreadLocal存放保证线程隔离&#xff0c;代码如下&#xff1a;/*** description 用户上下文信息*/ p…

深度学习毕设项目:基于CNN深度学习python的遥感图片识别沙漠湖泊和森林

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

【课程设计/毕业设计】基于python机器学习的猫狗表情识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

【建议收藏】AI 音乐提示词终极指南|全网最全的创作控制手册|Suno 进阶指南|第 15 篇

历史文章 Suno AI API接入 - 将AI音乐接入到自己的产品中&#xff0c;支持120并发任务 Suno用邓紫棋的声音唱《我不是真正的快乐》 | 进阶指南 | 第8篇 Suno 12 轨全轨分离导出midi伴奏分离实战&#xff5c;进阶指南&#xff5c;第 11 篇 续写卡在 2 秒&#xff1f;解决方案…

链表相加(二)

代码求解 public ListNode reverseList(ListNode pHead){if(pHead null){return null;}ListNode pre null;ListNode cur pHead;ListNode next pHead;while(cur!null){next cur.next;cur.next pre;pre cur;cur next;}return pre;}public ListNode addInList (ListNode h…

从一道前端面试题,谈 JS 对象存储特点和运算符执行顺序

本文大纲今天来看一道前端面试的代码输出题。 面试官提供了一段 Javascript 代码&#xff0c;要求给出这段代码运行后的输出结果。 const obj {a: 0, };obj[1] 0; obj[obj.a] obj.a; const values Object.values(obj); obj[values[1]] obj.a; console.log(obj);先分析这道…

在RabbitMQ中,怎么确保消息不会丢失?

为了确保消息不会丢失&#xff0c;可以从以下3个方面解决&#xff1a; 1.在创建队列的时候设置durable为true&#xff0c;发布消息的时候设置delivery为2&#xff0c;从而确保队列和消息都是持久的。 这样&#xff0c;就算是RabbitMQ服务器重启也不会造成消息的丢失。 2.开启发…

深度学习毕设项目:基于python的印刷体数字和字母识别基于python深度学习的印刷体数字和字母识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

大数据领域Zookeeper的集群配置自动化工具推荐

大数据基石的"自动建筑师"&#xff1a;Zookeeper集群配置自动化工具深度解析 关键词 Zookeeper集群、配置自动化、Ansible、Kubernetes Operator、云原生运维、分布式协调、故障容错 摘要 在大数据生态中&#xff0c;Zookeeper作为分布式系统的"协调大脑"&…

【交通标示识别】模板匹配雾霾交通标示识别【含GUI Matlab源码 14873期】

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;Matlab武动乾坤博客之家&#x1f49e;…

PO、VO、BO、DTO、DAO、POJO有什么区别?

PO&#xff08;Persistent Object&#xff09;持久化对象&#xff0c;主要用于和数据库交互&#xff0c;是数据库数据在内存中的镜像。 VO&#xff08;View Object&#xff09;视图对象&#xff0c;和前端展示强相关&#xff0c;按需组装前端需要的字段。 BO&#xff08;Busine…

MYSQL_安装与配置(超详细,仅需一篇就能帮你成功安装MYSQL)

上一篇博客相信大家都已经了解到博主要讲那个数据库了&#xff0c;跟着博主的步伐一起来配置和安装数据库吧&#xff01;&#xff01;&#xff01; **1.**使用Installer安装 1.1 下载最新版本Installer 官下载8.0.X的最新版本 &#xff0c;址&#xff1a;https://dev.mysql.…