Java BigDecimal总结

news2024/12/27 2:50:18

文章目录

  • Java BigDecimal总结
    • 概述
    • float 和 double的问题
    • 创建BigDecimal对象
      • BigDecimal.valueOf()源码分析
    • equals() 和 compareTo()
    • BigDecimal设置精度和舍入模式
      • 舍入模式介绍
    • BigDecimal转字符串
    • DecimalFormat 格式化
    • 总结

Java BigDecimal总结

概述

BigDecimal类在Java的java.math包中,可以处理超过16位有效位数的精确运算,而双精度浮点类型double只能处理16位有效数。

float 和 double的问题

float a = 1.0F;
float b = 0.9F;
System.out.println(a - b); //0.100000024

问题分析:

执行结果是0.100000024而不是0.1,这是因为计算机的资源是有限的,所以没办法用二进制精确到表示0.1,只能用近似值来表示,也就是在有限的精度下,最大化接近0.1的二进制数,这样也就出现了精度缺少的问题。

创建BigDecimal对象

可以使用new BigDecimal() BigDecimal.value()的这2种方式创建BigDecimal对象。

BigDecimal a = new BigDecimal(0.1);
BigDecimal b = BigDecimal.valueOf(0.1);
System.out.println(a); //0.1000000000000000055511151231257827021181583404541015625
System.out.println(b); //0.1

问题分析:

使用new BigDecimal() 仍然会出现精度问题,而使用BigDecimal.valueOf()则不会出现精度问题。

BigDecimal.valueOf()源码分析

public static BigDecimal valueOf(double val) {
    return new BigDecimal(Double.toString(val));
}

valueOf()方法的内部是先调用toString()方法,将浮点类型转为字符串,然后再使用构造方法创建对象。因此在使用构造方法创建对象时,应优先传递字符串类型。

将参数改为字符串后没有了精度问题:

BigDecimal c = new BigDecimal("0.1");
System.out.println(c); //0.1

equals() 和 compareTo()

比较2个BigDecimal对象,可以使用equals()compareTo()

BigDecimal a = new BigDecimal("0.01");
BigDecimal b = new BigDecimal("0.010");
System.out.println(a.equals(b)); //false
System.out.println(a.compareTo(b)); //0

问题分析:

equals()方法不仅比较2个对象的值是否相等,还比较精度是否相同。

compareTo()方法仅比较值的大小,返回值为:

  • -1:小于
  • 0:等于
  • 1:大于

因此,如果只比较2个对象的值的大小,则使用compareTo();如果严格限制精度的比较,则使用equals()

BigDecimal设置精度和舍入模式

在使用BigDecimal进行运算时,一定要设置精度和舍入模式,否则会出现以下问题:

BigDecimal a = new BigDecimal("1");
BigDecimal b = new BigDecimal("3");
System.out.println(a.divide(b));

报异常:

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
	at java.base/java.math.BigDecimal.divide(BigDecimal.java:1722)

问题分析:

这是因为在做除法运算时,遇到一个无限小数0.3333…,不是一个精确到数字,因此抛出ArithmeticException异常。

舍入模式介绍

入模式定义在RoundingMode枚举类中,共有8种:

  • RoundingMode.UP:舍入远离零的舍入模式。在丢弃非零部分之前始终增加数字(始终对非零舍弃部分前面的数字加1)。注意,此舍入模式始终不会减少计算值的大小。
  • RoundingMode.DOWN:接近零的舍入模式。在丢弃某部分之前始终不增加数字(从不对舍弃部分前面的数字加1,即截短)。注意,此舍入模式始终不会增加计算值的大小。
  • RoundingMode.CEILING:接近正无穷大的舍入模式。如果 BigDecimal 为正,则舍入行为与 ROUNDUP 相同;如果为负,则舍入行为与 ROUNDDOWN 相同。注意,此舍入模式始终不会减少计算值。
  • RoundingMode.FLOOR:接近负无穷大的舍入模式。如果 BigDecimal 为正,则舍入行为与 ROUNDDOWN 相同;如果为负,则舍入行为与 ROUNDUP 相同。注意,此舍入模式始终不会增加计算值。
  • RoundingMode.HALF_UP:向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。如果舍弃部分 >= 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。注意,这是我们在小学时学过的舍入模式(四舍五入)。
  • RoundingMode.HALF_DOWN:向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式。如果舍弃部分 > 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同(五舍六入)。
  • RoundingMode.HALF_EVEN:向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。如果舍弃部分左边的数字为奇数,则舍入行为与 ROUNDHALFUP 相同;如果为偶数,则舍入行为与 ROUNDHALF_DOWN 相同。注意,在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。此舍入模式也称为“银行家舍入法”,主要在美国使用。四舍六入,五分两种情况。如果前一位为奇数,则入位,否则舍去。以下例子为保留小数点1位,那么这种舍入方式下的结果。1.15 ==> 1.2 ,1.25 ==> 1.2
  • RoundingMode.UNNECESSARY:断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。

常用的四舍五入也就是RoundingMode.HALF_UP

加入精度和舍入模式后除法运算就正常了。

BigDecimal a = new BigDecimal("1");
BigDecimal b = new BigDecimal("3");
System.out.println(a.divide(b, 2, RoundingMode.HALF_UP)); //0.33

BigDecimal转字符串

BigDecimal对象转字符串有3种方法:

  • toPlainString():不适用科学计数法,通常使用最多。
  • toString():使用科学计数法。
  • toEngineeringString():使用工程计数法。

在这里插入图片描述

BigDecimal a = BigDecimal.valueOf(100000000000000000000.11);
System.out.println(a.toPlainString()); //100000000000000000000
System.out.println(a.toString()); //1.0E+20
System.out.println(a.toEngineeringString()); //100E+18

DecimalFormat 格式化

占位符说明
0数字占位符,位数不够时补0
#数字占位符,位数不够时省略
.小数点占位符
DecimalFormat format1 = new DecimalFormat("##.##");
System.out.println(format1.format(123.456)); //123.46
System.out.println(format1.format(3.4)); //3.4

DecimalFormat format2 = new DecimalFormat("00.00");
System.out.println(format2.format(123.456)); //123.46
System.out.println(format2.format(3.4)); //03.40

总结

  1. 如果使用new BigDecimal()方式创建对象,一定要传入字符串;否则使用BigDecimal.valueOf()方式创建对象。
  2. BigDecimal对象比较值大小时推荐使用compareTo()方法。
  3. 使用BigDecimal运算时一定要设置精度和舍入模式。
  4. BigDecimal转字符串推荐使用toPlainString()方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/126619.html

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

相关文章

一个简单的数学问题

这个东西发提问没人看就发在这里了 一个球体的体积V_Sphere是容易求的: 则我们很容易求出半径为1的圆球的体积为. 众所周知方程【】在三维笛卡尔坐标系中的图像为一个半径为R的圆, 则R取1时这个方程的图像就成了一个半径为1的圆。 那么我们就能推出f(x…

飞行机器人专栏(九)-- 多传感器固定端口分配

目录 ​编辑 1 /dev/设备列表 2 ttyUSB*端口ID 3 端口别名rules动态绑定 4 launch文件配置 1 /dev/设备列表 lsusblsusb -t 2 ttyUSB*端口ID 查看/dev/ttyUSB* 设备端口ID :0403:6014 找到对应USB的设备ID,这里是 0403:…

测试新风向|视频 AI 转流程图初体验

前言: 😄作者简介:小曾同学.com,小伙伴们也可以叫我小曾,一个致力于测试开发的博主⛽️ 如果文章知识点有错误的地方,还请大家指正,让我们一起学习,一起进步。😊 座右铭:…

极狐GitLab include 语法减少 CI/CD Pipeline 代码冗余,提升构建效率

项目经理:我们有个 Java 的新项目要开始了,需要你帮忙设置调试一下 CI/CD Pipeline DevOps 工程师:好的,没问题 ONE WEEK LATER... 项目经理:新项目的 CI/CD Pipeline 咋样了啊,我看研发还是手动人肉编译…

基于Vue+SpringBoot的在线考试系统,支持多种题型,含数据库文件

spring-boot-online-exam 完整代码下载地址:基于VueSpringBoot的在线考试系统 快速体验 在安装了docker的机器上执行如下命令: 安装mysql: docker run --name exam-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORDaA111111 -d mysql:5.7.15然后用doc/sql…

freeswitch的gateway实现出中继的主备方案

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 某些呼叫场景中,我们有2条出中继线路可选,2条出中继需要按照主备模式来配置,优先使用主中继呼叫,当主中继出现问题时,呼叫自动转移到备用中继呼叫。 本节中&a…

正大国际期货:恒指操作技巧之交易中五种绝佳的开仓思路分析

很多人总是亏损,其实最重要的原因之一是没有一个优势的概率系统,正大IxxxuanI经过了解之后,对目前市面上概率系统进行总结,现将以下几种优势的概率系统归纳罗列如下,有缘者定可举一反三,或可为你细化和改良…

Android中GRPC的使用-拦截器

在构建GRPC应用程序时,无论是客户端应用程序,还是服务端应用程序,在远程方法执行之前后之后,都可能需要执行一些通用逻辑。在GRPC中可以拦截RPC的执行,来满足特定的需求,如日志、认证、性能度量指标等&…

基于Amlogic 安卓9.0, 驱动简说(四):Platform平台驱动,驱动与设备的分离

一、篇头 本文介绍Platform平台驱动框架,使用此框架,将可以用上DTS设备树文件,实现设备的静态枚举,实现设备与驱动的分离。 本文基于Amlogic T972 , Android 9.0, 内核版本 4.9.113 二、系列文章 第1篇&a…

【Docker基础篇】一文完成快速使用

Docker基础篇前言Docker是什么?Docker与传统虚拟机技术区别Docker作用、为什么用docker原理Docker常用命令案例展示redis各种软件安装打包到本地、上传到远程仓库打包到本地推送到远程仓库前言 所有的权威均来自与官方,如有疑问请参考官网文献。人非圣贤…

网络厂商 Aruba 2022 年业绩成倍增长的经验是什么

转眼,2022 年马上就要结束了。 在多重不确定的经济环境之下,网络厂商 Aruba 中国在 2022 年的业绩,与上一财年相比仍然实现了成倍的增长。今年初,CSDN 曾采访过 Aruba 中国区的管理者 Aruba 中国区总经理谢建国与 Aruba 北中国区大…

alpine的介绍与使用

目录 1. alpine 简介 2. 基于alpine构建jdk8镜像 2.1 Dockerfile 2.2 将构建目录上传到linux中 2.3 执行构建 3. 镜像瘦身 4. 上传阿里云镜像仓库 1. alpine 简介 Alpine Linux是一个轻型Linux发行版,它不同于通常的Linux发行版,Alpine采用了musl …

【车间调度】基于卷积神经网络的柔性作业车间调度问题的两阶段算法(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

CryptoJS加密解密

1.CryptoJS CryptoJS库是前端js写的一个加密解密的工具,使用场景就是对于像账户密码等重要信息要显示在页面上时,需要加密,这样才能保证安全,CryptoJS提供了许多加密的方法, 请参考: cryptojs-JavaScrip…

OSPF的汇总实验

目录 1.拓扑图 2.实验要求 3.实验思路 4.主要配置 5.测试 6.实验总结 1.拓扑图 2.实验要求 R4为ISP,其上只能配置ip,R4与其他所有直连设备间使用公有ip;解决ospf不规则区域;整个ospf环境ip地址为172.16.0.0/16,…

pure pursuit纯跟踪

Pure Pursuit是一种几何追踪方法,速度越小,performance越好; :汽车前轮转角 L:前后轮轴距(车长) R:转弯半径 将车辆模型简化为自行车模型(这里默认左轮和右轮的旋转是一致的)!!! bicycle model: pure pursuit建立于自行车模型和阿克曼小车模型的基础上,goal point为距离后…

2022年用于Web开发的15种最佳编程语言

Web 开发是一个常青的领域,机会总是很多。自 90 年代初出现以来,开发行业在各种方式和领域中发展并蓬勃发展。今天,在 21 世纪,Web 开发仍然是最受欢迎的技能之一。要在这个领域开始职业生涯,掌握Web 开发语言是必不可…

UDS-10.4 SecurityAccess (27) service

10.4 安全访问(27)服务 来自:ISO 14229-1-2020.pdf 10.4.1 服务描述 本服务的目的是提供一种访问数据和/或诊断服务的方法,这些数据和/或诊断服务由于安全、排放或安全原因而被限制访问。用于将例程或数据下载/上传到服务器以及从服务器读取特定内存位置…

spring 基础知识-- IOC 和 DI 的配置和使用。

目录 一、基本概念 二、Spring 核心概念 1、问题分析 2、IOC、IOC容器、Bean、DI 3、IOC 入门案例 4、DI 入门案例 三、IOC 详解 1、bean 基础配置 2、bean 实例化 3、bean 生命周期 四、DI 详解 1、setter 注入 2、构造器注入 3、自动配置 4、集合注入 一、基…

go调度和性能分析利器之trace

trace的使用示例 import ("fmt""log""os""runtime/trace""sync" )func main() {//runtime.GOMAXPROCS(1)// 1. 创建trace持久化的文件句柄f, err : os.Create("trace.out")if err ! nil {log.Fatalf("failed…