记一次金额操作精度丢失问题与解决

news/2025/6/2 21:09:24

Hi, I’m Shendi


记一次金额操作精度丢失问题与解决




前言

在之前做过几个涉及到金额的项目,因我最开始接触的支付是微信支付,对于微信的设计,是以分为单位,金额为整数形式。知晓精度丢失的问题,我也照着这样,将金额设计成整数。

对于小数存储,在代码中使用的double,因为数据库中是以整数存储,而小数计算的地方实际上不是很多,只有在给用户展示时将 金额/100,以及在一些输入或接收到的金额为小数字符串(支付宝支付)的时候,将 金额*100

想得挺简单,因为在我的认知中精度只有两位小数,而且进行的操作都是小数乘以或除以100,出现精度丢失的可能性应该不大

在之前编写了一个另类支付方式,一个 SPay APP,涉及到了金额的截取,发现过精度丢失的问题,是因为默认小数是double类型,我在计算后使用float类型存储,导致精度丢失,于是使用double存储问题就解决了。也尝试将数字进行替换进行测试,没有发现任何问题…



问题出现

在今天,发现了精度丢失的问题。我的代码是这样的

int amount = (int) (Double.parseDouble(amountStr) * 100);

其中 amountStr 为 0.58,最后的结果为 57。

在这里插入图片描述



测试与解决

在之前我觉得像这种 * 100与 / 100的操作按道理来说应该不会出现精度丢失问题,但现在问题就这样摆在眼前。

我将Double换成float,问题就解决了。

在这里插入图片描述

但就像之前一样,我不确定这样在我的场景中是否还会出现精度丢失问题。于是开始寻找对于我这种只有两位小数的关于 float 精度丢失的示例,但并没有结果。

我知道关于金额操作,保持高精度有一种解决办法是使用 BigDecimal,但这对性能有一定的损耗。就像上面这样的示例,简单试一下运行时间

在这里插入图片描述


在这里插入图片描述


大概是测试不够严谨,使用BigDecimal与直接基础类型计算耗时居然相似!

既然这样,那就直接选择使用BigDecimal了。

经过测试,需要注意的是,创建BigDecimal最好是使用字符串。否则也有可能出现精度丢失问题,例如上面说的0.58*100,如果不是字符串,依然精度丢失…

在这里插入图片描述


总结:

对于重要的小数操作皆使用BigDecimal,且能用字符串创建尽量用字符串创建。这样,大概就不会再出现精度丢失这种令人头疼又不可控的问题了吧?



吐槽

一个好的东西一定是站在使用者的角度上来考虑,对于上面这样精度丢失的问题属实唏嘘,为什么不直接提供一个不会丢失精度的类型呢?毕竟我们只是使用者,关心的大多是业务与流程,对于性能部分那都是后话了。

自然而然的就有着这样的疑问,为什么不用BigDecimal将double与float取代?默认小数类型使用BigDecimal,毕竟,谁也不想自己写的程序好好的突然出现bug然后去更改吧。

但存在即合理,那些开发者们大抵考虑过这种问题,可能权衡利弊后,选择了保持现状。




END

文章来源:https://blog.csdn.net/qq_41806966/article/details/134906239
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:https://dhexx.cn/news/show-5177734.html

相关文章

Leetcode—231.2的幂【简单】

2023每日刷题&#xff08;五十四&#xff09; Leetcode—231.2的幂 实现代码 class Solution { public:bool isPowerOfTwo(int n) {if(n < 0) {return false;}long long ans 1;while(ans < n) {ans * 2;}if(ans n) {return true;}return false;} };运行结果 之后我会…

【面试经典150 | 二叉树】从中序与后序遍历序列构造二叉树

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;递归 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容…

国内大厂机器人赛道产品

大疆 大疆无人机自然不必说&#xff0c;除此之外大疆搞机甲大师&#xff0c;教育机器人。 字节 当前字节在机器人领域只是初步探索阶段&#xff0c;目前尚未发布相关产品&#xff08;截止至23.12&#xff09;。 管理层想法&#xff1a; 跟已有业务做结合&#xff0c;服务好…

rpc原理与应用

IPC和RPC&#xff1f; RPC 而RPC&#xff08;Remote Procedure Call&#xff09;&#xff0c;又叫做远程过程调用。它本身并不是一个具体的协议&#xff0c;而是一种调用方式。 gRPC 是 Google 最近公布的开源软件&#xff0c;基于最新的 HTTP2.0 协议&#xff0c;并支持常见…

【解密考研英语:Python数据分析与可视化】

解密考研英语&#xff1a;Python数据分析与可视化 背景数据集技术选型功能实现创新点 大家好&#xff0c;欢迎阅读我的CSDN博客&#xff01;今天我将分享一项有关考研英语真题的数据分析与可视化项目&#xff0c;希望对考研学子提供更有针对性的复习帮助。 背景 作为考研学子…

元素定位,年轻人在 Web UI 自动化成长道路上吃的第一个亏

01/Katalon Studio 的 Web spy spy 英文翻译过来的意思是&#xff1a;间谍、密探。是具有监视意识的。 所以我们可以使用这个功能去监视 Web 元素并定位出来。具体操作如下&#xff1a;1&#xff0c;打开 Katalon 并创建好项目工程 2&#xff0c;在快捷键栏里点击 Web spy 如…

Java面试遇到的一些常见题

目录 1. Java语言有几种基本类型&#xff0c;分别是什么&#xff1f; 整数类型&#xff08;Integer Types&#xff09;&#xff1a; 浮点类型&#xff08;Floating-Point Types&#xff09;&#xff1a; 字符类型&#xff08;Character Type&#xff09;&#xff1a; 布尔类…

【Linux】:线程(二)互斥

互斥与同步 一.线程的局部存储二.线程的分离三.互斥1.一些概念2.上锁3.锁的原理4.死锁 一.线程的局部存储 例子 可以看到全局变量是所有线程共享的&#xff0c;如果我们想要每个线程都单独访问g_val怎么办呢&#xff1f;其实我们可以在它前面加上__thread修饰。 这就相当于把g…

我的创作纪念日——一年

机缘 初心始于对技术的热爱和分享知识的渴望。最初&#xff0c;我在一次练习中遇到了一些问题&#xff0c;通过解决这些问题并将解决方案记录下来&#xff0c;我意识到分享经验对自己和他人都非常有价值。于是&#xff0c;我开始在博客和社交平台上记录日常学习过程、撰写技术…

重心坐标:定义、公式与应用

重心坐标&#xff08;Barycentric Coordinates&#xff09;在 CG 中尤为重要。 它们有一些功能&#xff0c;是 Mller-Trumbore 提出的下一个射线三角形相交算法的关键&#xff0c;该算法将在下一章中研究。 本章最后将讨论如何在 CG 中使用重心坐标。 NSDT工具推荐&#xff1a;…