BigDecimal精度丢失问题
创始人
2024-02-02 05:44:19

浅谈BigDecimal精度丢失问题

文章目录

    • 浅谈BigDecimal精度丢失问题
      • 一. 简介
      • 二. 错误使用
      • 三. 原因分析
      • 四. 正确使用


一. 简介

​ Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作。

二. 错误使用

在我们的日常开发中,对于金钱的处理我们都会使用BigDecimal进行处理,但是如果我们不熟悉使用的话,很容易出现如下的错误使用方式。
代码演示:


import java.math.BigDecimal;public class DecimalTest {public static void main(String[] args) {BigDecimal bd1 = new BigDecimal(0.1);System.out.println("bd1的值:"+bd1);}
}

在这里插入图片描述
从上面的执行可以看出,java中进行浮点数运算的时候,会出现丢失精度的问题。那么我们如果在进行价格计算的时候,就会出现问题。

三. 原因分析

计算机组成原理里面都有,它们的编码决定了这样的结果。
long可以准确存储19位数字,而double只能准确存储16位数字。

double由于有exp位,可以存16位以上的数字,但是需要以低位的不精确作为代价。如果需要高于19位数字的精确存储,则必须用BigInteger来保存,当然会牺牲一些性能。

源码注释解读:

 /*** Translates a {@code double} into a {@code BigDecimal} which* is the exact decimal representation of the {@code double}'s* binary floating-point value.  The scale of the returned* {@code BigDecimal} is the smallest value such that* (10scale × val) is an integer.* 

* Notes:*

    *
  1. * The results of this constructor can be somewhat unpredictable.* One might assume that writing {@code new BigDecimal(0.1)} in* Java creates a {@code BigDecimal} which is exactly equal to* 0.1 (an unscaled value of 1, with a scale of 1), but it is* actually equal to* 0.1000000000000000055511151231257827021181583404541015625.* This is because 0.1 cannot be represented exactly as a* {@code double} (or, for that matter, as a binary fraction of* any finite length). Thus, the value that is being passed* in to the constructor is not exactly equal to 0.1,* appearances notwithstanding.**
  2. * The {@code String} constructor, on the other hand, is* perfectly predictable: writing {@code new BigDecimal("0.1")}* creates a {@code BigDecimal} which is exactly equal to* 0.1, as one would expect. Therefore, it is generally* recommended that the {@linkplain #BigDecimal(String)* String constructor} be used in preference to this one.**
  3. * When a {@code double} must be used as a source for a* {@code BigDecimal}, note that this constructor provides an* exact conversion; it does not give the same result as* converting the {@code double} to a {@code String} using the* {@link Double#toString(double)} method and then using the* {@link #BigDecimal(String)} constructor. To get that result,* use the {@code static} {@link #valueOf(double)} method.*
** @param val {@code double} value to be converted to* {@code BigDecimal}.* @throws NumberFormatException if {@code val} is infinite or NaN.*/public BigDecimal(double val) {this(val,MathContext.UNLIMITED);}
  • 第一段也说的很清楚它只能计算的无限接近这个数,但是无法精确到这个数。
  • 第二段则说,如果要想准确计算这个值,那么需要把double类型的参数转化为String类型的。并且使用BigDecimal(String)这个构造方法进行构造。去获取结果。

四. 正确使用

我们一般使用BigDecimal来解决商业运算上丢失精度的问题的时候,声明BigDecimal对象的时候一定要使用它构造参数为String的类型的构造器。

代码演示:

import java.math.BigDecimal;public class DecimalTest {public static void main(String[] args) {// 错误使用方式BigDecimal bd1 = new BigDecimal(0.1);System.out.println("bd1的值:"+bd1);// 正确使用方式BigDecimal bd2 = new BigDecimal("0.1");System.out.println("bd2的值:"+bd2);}
}

另外,BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。

相关内容

热门资讯

应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...