广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java精确计算BigDecimal类详解
  • 481
分享到

Java精确计算BigDecimal类详解

2024-04-02 19:04:59 481人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

引言 float和double类型的主要设计目标是为了科学计算和工程计算。他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的。然而,它们没有提供完

引言

float和double类型的主要设计目标是为了科学计算和工程计算。他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的。然而,它们没有提供完全精确的结果,所以不应该被用于要求精确结果的场合。但是,商业计算往往要求结果精确,这时候BigDecimal就派上大用场啦。

先看下面代码


public static void main(String[] args)
    {
        System.out.println(0.2 + 0.1);
        System.out.println(0.3 - 0.1);
        System.out.println(0.2 * 0.1);
        System.out.println(0.3 / 0.1);
    }

运行结果如下

你认为你看错了,但结果却是是这样的。问题在哪里呢?原因在于我们的计算机是二进制的。浮点数没有办法是用二进制进行精确表示。我们的CPU表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。如:2.4的二进制表示并非就是精确的2.4。反而最为接近的二进制表示是2.3999999999999999。浮点数的值实际上是由一个特定的数学公式计算得到的。

其实java的float只能用来进行科学计算或工程计算,在大多数的商业计算中,一般采用java.math.BigDecimal类来进行精确计算。

BigDecimal构造方法

  • 1.public BigDecimal(double val) 将double表示形式转换为BigDecimal *不建议使用
  • 2.public BigDecimal(int val)  将int表示形式转换成BigDecimal
  • 3.public BigDecimal(String val)  将String表示形式转换成BigDecimal

为什么不建议采用第一种构造方法呢?来看例子


public static void main(String[] args)
    {
        BigDecimal bigDecimal = new BigDecimal(2);
        BigDecimal bDouble = new BigDecimal(2.3);
        BigDecimal bString = new BigDecimal("2.3");
        System.out.println("bigDecimal=" + bigDecimal);
        System.out.println("bDouble=" + bDouble);
        System.out.println("bString=" + bString);
    }

运行结果如下

为什么会出现这种情况呢?

jdk的描述:

1、参数类型为double的构造方法的结果有一定的不可预知性。有人可能认为在Java中写入newBigDecimal(0.1)所创建的BigDecimal正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。

2、另一方面,String 构造方法是完全可预知的:写入 newBigDecimal("0.1") 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言,通常建议优先使用String构造方法

当double必须用作BigDecimal的源时,请使用Double.toString(double)转成String,然后使用String构造方法,或使用BigDecimal的静态方法valueOf,如下


public static void main(String[] args)
    {
        BigDecimal bDouble1 = BigDecimal.valueOf(2.3);
        BigDecimal bDouble2 = new BigDecimal(Double.toString(2.3));

        System.out.println("bDouble1=" + bDouble1);
        System.out.println("bDouble2=" + bDouble2);
        
    }

结果如下

BigDecimal加减乘除运算

对于常用的加,减,乘,除,BigDecimal类提供了相应的成员方法。


public BigDecimal add(BigDecimal value);                        //加法

public BigDecimal subtract(BigDecimal value);                   //减法 

public BigDecimal multiply(BigDecimal value);                   //乘法

public BigDecimal divide(BigDecimal value);                     //除法

大概的用法如下


public static void main(String[] args)
    {
        BigDecimal a = new BigDecimal("4.5");
        BigDecimal b = new BigDecimal("1.5");

        System.out.println("a + b =" + a.add(b));
        System.out.println("a - b =" + a.subtract(b));
        System.out.println("a * b =" + a.multiply(b));
        System.out.println("a / b =" + a.divide(b));
    }

运行结果

这里有一点需要注意的是除法运算divide.

BigDecimal除法可能出现不能整除的情况,比如 4.5/1.3,这时会报错java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

其实divide方法有可以传三个参数

public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) 

第一参数表示除数, 第二个参数表示小数点后保留位数

第三个参数表示舍入模式,只有在作除法运算或四舍五入时才用到舍入模式,有下面这几种


ROUND_CEILING    //向正无穷方向舍入

ROUND_DOWN    //向零方向舍入

ROUND_FLOOR    //向负无穷方向舍入

ROUND_HALF_DOWN    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5

ROUND_HALF_EVEN    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP,如果是偶数,使用ROUND_HALF_DOWN

ROUND_HALF_UP    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6

ROUND_UNNECESSARY    //计算结果是精确的,不需要舍入模式

ROUND_UP    //向远离0的方向舍入

按照各自的需要,可传入合适的第三个参数。四舍五入采用ROUND_HALF_UP

需要对BigDecimal进行截断和四舍五入可用setScale方法,例:


public static void main(String[] args)
    {
        BigDecimal a = new BigDecimal("4.5635");

        a = a.setScale(3, RoundingMode.HALF_UP);    //保留3位小数,且四舍五入
        System.out.println(a);
    }

减乘除其实最终都返回的是一个新的BigDecimal对象,因为BigInteger与BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象 


public static void main(String[] args)
    {
        BigDecimal a = new BigDecimal("4.5");
        BigDecimal b = new BigDecimal("1.5");
        a.add(b);

        System.out.println(a);  //输出4.5. 加减乘除方法会返回一个新的BigDecimal对象,原来的a不变


    }

总结

  • (1)商业计算使用BigDecimal。
  • (2)尽量使用参数类型为String的构造函数。
  • (3)BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以在做加减乘除运算时千万要保存操作后的值。
  • (4)我们往往容易忽略JDK底层的一些实现细节,导致出现错误,需要多加注意。

到此这篇关于Java精确计算BigDecimal类详解的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: Java精确计算BigDecimal类详解

本文链接: https://www.lsjlt.com/news/159682.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java精确计算BigDecimal类详解
    引言 float和double类型的主要设计目标是为了科学计算和工程计算。他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的。然而,它们没有提供完...
    99+
    2022-11-12
  • Java精确计算BigDecimal类怎么使用
    本篇内容主要讲解“Java精确计算BigDecimal类怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java精确计算BigDecimal类怎么使用”吧!引言float和double类型...
    99+
    2023-06-25
  • Java高精度计算BigDecimal类实例分析
    这篇文章主要介绍了Java高精度计算BigDecimal类实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java高精度计算BigDecimal类实例分析文章都会有所收获,下面我们一起来看看吧。如果我们编...
    99+
    2023-06-03
  • 详解java中BigDecimal精度问题
    目录一、背景二、BigDecimal构造函数1、四种构造函数2、为什么会出现这种情况3、如何解决三、常用方法1、常用方法2、取舍规则四、格式化一、背景 在实际开发中,对于 不需要任何...
    99+
    2022-11-12
  • Java BigDecimal正确用法详解
    目录一、背景二、事故案例1、问题2、问题复现3、源码分析4、原因分析三、总结四、工具类一、背景 BigDecimal 平时主要用于计算金钱时,其自身提供了很多的构造方法,但是这些构造...
    99+
    2022-11-13
  • java BigDecimal类案例详解
    目录前言一.介绍二.知识点介绍三.知识点详解1、概述2、BigDecimal构造方法3、源码的描述4、BigDecimal加减乘除运算5、总结6、精炼练习6.1  题目6....
    99+
    2022-11-13
  • Java BigDecimal类用法详解
    一、简介 Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中...
    99+
    2022-11-12
  • Java中的高精度计算怎么利用BigDecimal实现
    本篇文章给大家分享的是有关Java中的高精度计算怎么利用BigDecimal实现,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。首先看如下代码示例:System.out.prin...
    99+
    2023-05-31
    java ava bigdecimal
  • Java中怎么精确计算浮点数
    今天就跟大家聊聊有关Java中怎么精确计算浮点数,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。问题的提出:XML:namespace prefix = o ns = "ur...
    99+
    2023-06-03
  • BigDecimal的加减乘除计算方法详解
    目录BigDecimal的运算——加减乘除 首先是bigdecimal的初始化加法 add()函数     减法subtract()...
    99+
    2022-11-12
  • Java日期时间类及计算详解
    目录1. Java中与日期相关的类1.1 java.util包① Date类② Calendar 日历类roll设置Calendar的容错性set1.2 java.time包① Lo...
    99+
    2022-11-13
  • python中实现精确的浮点数运算详解
    为什么说浮点数缺乏精确性? 在开始本文之前,让我们先来谈谈浮点数为什么缺乏精确性的问题,其实这不是Python的问题,而是实数的无限精度跟计算机的有限内存之间的矛盾。 举个例子,假如说我只能使用整数(即只精...
    99+
    2022-06-04
    详解 精确 浮点数
  • Java设计模式UML之类图精解
    目录1.UML基本介绍2.UML类图2.1类关系——依赖2.2类关系——泛化2.3类关系——实现2.4类关系——关联2.5类关系——聚合2.6类关系——组合1.UML基本介绍 ...
    99+
    2022-11-13
  • Python+decimal完成精度计算的示例详解
    目录1. 浮点数转Decimal2. Decimal除法设置3. Quantize设置结果4. Decimal精度设置在进行小数计算的时候使用float...
    99+
    2022-11-11
  • Java六类运算符详解
    目录算数运算符关系运算符逻辑运算符赋值运算符字符串连接运算符条件运算符在 Java 语言中,运算符有算数运算符、关系运算符、逻辑运算符、赋值运算符、字符串连接运算符、条件运算符。 算...
    99+
    2023-03-21
    算数运算符 关系运算符 逻辑运算符 赋值运算符 字符串连接运算符 条件运算符
  • 【Java基础教程】(三十六)常用类库篇 · 第六讲:数学运算类——全面讲解Java数学计算支持类库,BigDecimal、Math、Random、DecimalFormat...~
    Java基础教程之常用类库 · 数学运算类 1️⃣ 概念🔍 数学运算类汇总 2️⃣ 优势和缺点3️⃣ 使用3.1 各数学计算支持类使用案例3.2 Math类3.3 BigDecimal类3.4 Random...
    99+
    2023-08-16
    java python 数据库 经验分享 开发语言 后端 算法
  • Python计算分类问题的评价指标(准确率、精确度、召回率和F1值,Kappa指标)
    机器学习的分类问题常用评论指标有:准确率、精确度、召回率和F1值,还有kappa指标 。 每次调包去找他们的计算代码很麻烦,所以这里一次性定义一个函数,直接计算所有的评价指标。 每次输入预测值和真实值就可以得到上面的指标值,很方便。 下面...
    99+
    2023-09-17
    分类 机器学习 pandas 数据挖掘 python
  • 详解节点监控相对准确的计算FMP
    目录引言如何监控节点监控变化节点标记什么时间计算?为什么?怎么筛选元素?计算权重得分基础节点父节点排除干扰项不可见元素处理方案滚动偏移处理方案不同元素 FMP 算法不同普通元素资源元...
    99+
    2023-01-10
    节点监控FMP计算 相对准确FMP计算
  • 精辟全面且细致的java运算符教程详解
    目录前言一、算术运算符1.1 int/int结果还是int1.2 0不能作为除数1.3 关于%1.4 增量赋值运算符+= -= *= /=1.5 自增或自减运算二、关系运算符三、逻辑...
    99+
    2022-11-12
  • 详解php如何正确计算中文字符串的长度
    在PHP编程中,我们常常遇到需要计算字符串长度的场景。一般情况下,我们习惯用 strlen() 函数或 mb_strlen() 函数来计算字符串长度。然而,在处理中文字符串时,我们会发现使用 strlen() 函数会出现问题,因为中文字符不...
    99+
    2023-05-14
    php字符串 php
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作