BigDecimal解决精度问题

server/2025/1/1 11:31:42/

前提

对于需要精确计算得场景和一些需要精确保留小数位的场景,可以使用BigDeciaml来做操作

举个例子,两数相乘或者相除:

java">        double a = 1.235;double b = 100.00;System.out.println(a * b);  // 期望结果:123.4double c = 123.30;double d = 100.00;System.out.println(c / d); //期望结果:1.233

实际结果:

123.50000000000001
1.2329999999999999

使用BigDeciaml

java">        BigDecimal a = new BigDecimal("1.235");BigDecimal b = new BigDecimal("100.00");BigDecimal c = new BigDecimal("123.30");BigDecimal d = new BigDecimal("100.00");System.out.println(a.multiply(b));System.out.println(c.divide(d));

实际结果:

123.50000
1.233

构建

使用字符串来构造BigDecimal对象,如下

java">BigDecimal bd = new BigDecimal("0.1");  

错误做法:

下面这种,使用double类型的参数构造BigDecimal,会有精度问题,不要使用

java">BigDecimal bd = new BigDecimal(0.1);  

结果:

0.1000000000000000055511151231257827021181583404541015625

常用方法

  1. add(BigDecimal)

BigDecimal对象中的值相加,返回BigDecimal对象

  1. subtract(BigDecimal)

BigDecimal对象中的值相减,返回BigDecimal对象

  1. multiply(BigDecimal)

BigDecimal对象中的值相乘,返回BigDecimal对象

  1. divide(BigDecimal)

BigDecimal对象中的值相除,返回BigDecimal对象

  1. toString()

将BigDecimal对象中的值转换成字符串

  1. doubleValue()

将BigDecimal对象中的值转换成双精度数

  1. floatValue()

将BigDecimal对象中的值转换成单精度数

  1. longValue()

将BigDecimal对象中的值转换成长整数

  1. intValue()

将BigDecimal对象中的值转换成整数

  1. compareTo(BigDecimal val);

比较大小:-1小于;0相等;1大于

java">    System.out.println(new BigDecimal("0.1").compareTo(new BigDecimal("0.2")));System.out.println(new BigDecimal("0.2").compareTo(new BigDecimal("0.1")));System.out.println(new BigDecimal("0.123").compareTo(new BigDecimal("0.123000000")));

结果:

-1
1
0
  1. BigDecimal setScale(int newScale, int roundingMode)

roundingMode:

public static final int ROUND_HALF_UP = 4; //向上取

public static final int ROUND_HALF_DOWN = 5; //向下取

.......

java">BigDecimal bigDecimal = new BigDecimal("0.12345678").setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println(bigDecimal);

结果:

0.12

工具类

java">
public class BigDecimalUtils {/*** 除法默认保留精度*/private static final int DEF_DIV_SCALE = 10;/*** 默认舍入模式(ROUND_HALF_UP:四舍五入)*/private static final int DEF_ROUNDING_MODE = BigDecimal.ROUND_HALF_UP;private static final String FORMAT_1 = "#.##";/*** 将字符串转换为 BigDecimal** @param value* @return*/public static BigDecimal of(String value) {return value == null ? null : new BigDecimal(value);}/*** v1 + v2** @param v1 被加数* @param v2 加数* @return 两个参数的和*/public static BigDecimal add(BigDecimal v1, BigDecimal v2) {return v1.add(v2);}/*** args[0] + args[1] + ... + args[n]** @param args* @return*/public static BigDecimal add(BigDecimal... args) {if (args == null || args.length <= 1) {throw new IllegalArgumentException("args Contains at least two parameters");}BigDecimal result = args[0];for (int i = 1; i < args.length; i++) {result = add(result, args[i]);}return result;}/*** v1 - v2** @param v1 被加数* @param v2 加数* @return 两个参数的和*/public static BigDecimal subtract(BigDecimal v1, BigDecimal v2) {return v1.subtract(v2);}/*** args[0] - args[1] - ... - args[n]** @param args* @return*/public static BigDecimal subtract(BigDecimal... args) {if (args == null || args.length <= 1) {throw new IllegalArgumentException("args Contains at least two parameters");}BigDecimal result = args[0];for (int i = 1; i < args.length; i++) {result = subtract(result, args[i]);}return result;}/*** v1 * v2** @param v1 被乘数* @param v2 乘数* @return 两个参数的积*/public static BigDecimal multiply(BigDecimal v1, BigDecimal v2) {return v1.multiply(v2);}/*** args[0] * args[1] * ... * args[n]** @return 两个参数的积*/public static BigDecimal multiply(BigDecimal... args) {if (args == null || args.length <= 1) {throw new IllegalArgumentException("args Contains at least two parameters");}BigDecimal result = args[0];for (int i = 1; i < args.length; i++) {result = multiply(result, args[i]);}return result;}/*** v1 / v2** @param v1 被乘数* @param v2 乘数* @return 两个参数的积*/public static BigDecimal divide(BigDecimal v1, BigDecimal v2) {return v1.divide(v2, DEF_DIV_SCALE, DEF_ROUNDING_MODE);}/*** args[0] / args[1] / ... / args[n]** @return 两个参数的积*/public static BigDecimal divide(BigDecimal... args) {if (args == null || args.length <= 1) {throw new IllegalArgumentException("args Contains at least two parameters");}BigDecimal result = args[0];for (int i = 1; i < args.length; i++) {result = divide(result, args[i]);}return result;}/*** 四舍五入,保留两位小数** @param d* @return*/public static BigDecimal round(BigDecimal d) {if (d == null) {return null;}return d.setScale(2, BigDecimal.ROUND_HALF_UP);}/*** v1>v2?** @param v1* @param v2* @return*/public static boolean gt(BigDecimal v1, BigDecimal v2) {return v1.compareTo(v2) > 0;}/*** v1 == v2** @param v1* @param v2* @return*/public static boolean eq(BigDecimal v1, BigDecimal v2) {return v1.compareTo(v2) == 0;}/*** 判断 values 是否等于 0?** @param value* @return*/public static boolean eq0(BigDecimal value) {return BigDecimal.ZERO.compareTo(value) == 0;}/*** v1>=v2?** @param v1* @param v2* @return*/public static boolean ge(BigDecimal v1, BigDecimal v2) {return v1.compareTo(v2) >= 0;}/*** v1<v2?** @param v1* @param v2* @return*/public static boolean lt(BigDecimal v1, BigDecimal v2) {return v1.compareTo(v2) < 0;}/*** 格式化,保留2为小数** @param value* @return*/public static String format(BigDecimal value) {if (value == null) {return null;}DecimalFormat df = new DecimalFormat(FORMAT_1);return df.format(value);}/*** 格式化** @param value* @param pattern 模式字符串,如:#.##* @return*/public static String format(BigDecimal value, String pattern) {if (value == null) {return null;}DecimalFormat df = new DecimalFormat(pattern);return df.format(value);}}

http://www.ppmy.cn/server/154326.html

相关文章

深度学习:从原理到搭建基础模型

引言: 深度学习为什么火? 深度学习在处理复杂的感知和模式识别任务方面展现出了前所未有的能力。以图像识别为例,深度学习模型(如卷积神经网络 CNN)能够识别图像中的各种物体、场景和特征,准确率远超传统的计算机视觉方法。 当然这之中也还因为 大数据时代的推动(随着…

STM32单片机芯片与内部48 CAN 数据手册 寄存器

目录 一、CAN控制和状态寄存器 1、CAN主控制寄存器 (CAN_MCR) 2、CAN主状态寄存器 (CAN_MSR) 3、CAN发送状态寄存器 (CAN_TSR) 4、CAN接收FIFO 0寄存器 (CAN_RF0R) 5、CAN接收FIFO 1寄存器(CAN_RF1R) 6、CAN中断使能寄存器 (CAN_IER) 7、CAN错误状态寄存器 (CAN_ESR) …

Java 网络原理 ①-IO多路复用 || 自定义协议 || XML || JSON

这里是Themberfue 在学习完简单的网络编程后&#xff0c;我们将更加深入网络的学习——HTTP协议、TCP协议、UDP协议、IP协议........... IO多路复用 ✨在上一节基于 TCP 协议 编写应用层代码时&#xff0c;我们通过一个线程处理连接的申请&#xff0c;随后通过多线程或者线程…

Linux -Vim

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【Linux】 欢迎点赞&#x1f44d;收藏⭐关注❤️ 文章目录 &#x1f4da; 前言⚙️ 基本模式&#x1f4dd; 命令模式常见操作&#x1f4c4; 底行模式常见操作&#x1f6e0;️ 自定义 Vim 配置✨ 补充点 &#x1f4da; 前言…

HarmonyOS NEXT 实战之元服务:静态案例效果--- 我的一课表

背景&#xff1a; 前几篇学习了元服务&#xff0c;后面几期就让我们开发简单的元服务吧&#xff0c;里面丰富的内容大家自己加&#xff0c;本期案例 仅供参考 先上本期效果图 &#xff0c;里面图片自行替换 效果图1完整代码案例如下&#xff1a; import { authentication } …

华水967数据结构2023真题---选择题部分

一、选择题 1. 以下说法正确的是&#xff08;&#xff09; A.数据元素是数据最小单位 B.数据项是数据的基本单位 C.数据结构是带有结构的各数据项的集合 D.一些表面上很不相同的数据可以有相同的逻辑结构 答案&#xff1a;D 解析&#xff1a; A. 数据元素是数据的最小单位。 …

llamafactory报错:双卡4090GPU,训练qwen2.5:7B、14B时报错GPU显存不足(out of memory),轻松搞定~~~

实际问题场景&#xff1a; 使用llamafactory进行微调qwen2.5 7B和14B的大模型时&#xff0c;会出现out of memory的报错。尝试使用降低batch_size&#xff08;原本是2&#xff0c;现在降到1&#xff09;的方式&#xff0c;可以让qwen2.5:7B跑起来&#xff0c;但时不时会不稳定…

王佩丰24节Excel学习笔记——第二十二讲:制作甘特图与动态甘特图

【以 Excel2010 系列学习&#xff0c;用 Office LTSC 专业增强版 2021 实践】 【本章技巧】 插入图表&#xff0c;针对每一个图表上的元素&#xff0c;都可以选中选右键进行修改数据&#xff1b;本章中的向两端延伸&#xff0c;设置数据的原理&#xff1b;数据格式的显示方式&…