首页 > 编程知识 正文

bigdecimal什么意思(bigdecimal提高精度)

时间:2023-05-03 15:49:05 阅读:100441 作者:953

基本上我们已经形成了常识,在需要钱的地方,应该用BigDecimal而不是其他,大家都知道浮点变量在计算的时候会失去准确性。

那么,你知道BigDecimal会失去准确性吗?使用BigDecimal背后有什么值得探索的地方吗?今天,我告诉你,我知道为什么,为什么。

以下代码:

system . out . println(0.050.01);system . out . println(1.0-0.42);system . out . println(4.015 * 100);system . out . println(123.3/100);

输出:0.06000000000000000000050.500000000004

可以看出,在Java中进行浮点运算时,会出现失准的问题。那么如果我们计算商品的价格,就会出现问题。

很有可能我们手里有0.06元,却买不到一个0.05元和一个0.01元的商品。

因为如上图,它们的总和是0.060000005。

这无疑是一个非常严重的问题,尤其是当电商网站的并发量上去之后,问题将是巨大的。这可能导致无法下订单或对账问题。所以接下来,我们可以用Java中的BigDecimal类来解决这类问题。

普及一下:

Java中float的精度是6-7个有效数字。双精度是15-16位。

应用程序接口

构造函数:

构造函数描述BigDecimal(int)用参数指定的整数值创建一个对象。BigDecimal(double)用参数指定的双精度值创建一个对象。大十进制(长)用参数指定的长整数值创建一个对象。BigDecimal(字符串)创建一个对象,其数值由参数指定为字符串。

功能:

方法描述在add(BigDecimal) BigDecimal对象中添加值,然后返回该对象。减法(BigDecimal) BigDecimal)减去BigDecimal对象中的值,然后返回该对象。乘法(大十进制)将大十进制对象中的值相乘,然后返回该对象。将BigDecimal对象中的值除(BigDecimal),然后返回该对象。ToString()将BigDecimal对象的数值转换为字符串。DoubleValue()以双精度形式返回BigDecimal对象中的值。FloatValue()以单精度形式返回BigDecimal对象中的值。LongValue()以长整数形式返回BigDecimal对象中的值。IntValue()以整数形式返回BigDecimal对象中的值。

由于通用的数字类型,如双精度,超过16位的数字无法准确表示。

00-1010当我们使用BigDecimal时,使用它的BigDecimal(String)构造函数来创建对象是有意义的。其他的,比如BigDecimal b=new BigDecimal(1),仍然存在丢失精度的问题。以下代码:

BigDecimal a=新的big decimal(1.01);BigDecimal b=新的BigDecimal(1.02);BigDecimal c=新的big decimal(' 1.01 ');BigDecimal d=新的big decimal(' 1.02 ');system . out . println(a . add(b));system . out . println(c . add(d));

产量:2.030000000000000002645352591003 7569715

可以看出,BigDecimal的损失精度更为极端。但是,在使用Bigdecimal的BigDecimal(String)构造函数操作变量时,就没有这样的问题。

原因全在计算机组成原理,它们的编码决定了这个结果。

Long可以准确存储19位数字,double只能准备存储16位数字。

Double可以存储16位以上,因为它有exp位,但需要以低阶不精确为代价。如果需要准确存储19位以上,必须使用BigInteger保存,当然要牺牲一些性能。

因此,当我们一般使用BigDecimal来解决业务操作中精度丢失的问题时,在声明BigDecimal对象时,必须使用它来构造一个参数为String的类型的构造函数。

同时,这个原理在Effective Java和MySQL中也有。

提及。float和double只能用来做科学计算和工程计算。商业运算中我们要使用BigDecimal。

而且我们从源码的注释中官方也给出了说明,如下是BigDecimal类的double类型参数的构造器上的一部分注释说明:

* The results of this constructor can be somewhat unpredictable. * One might assume that writing {@codenew 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 * {@codedouble} (or, for that matter, as a binary fraction of * any finite length). Thus, the value that is being passed * <i>in</i> to the constructor is not exactly equal to 0.1, * appearances notwithstanding. …… * When a {@codedouble} 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 {@codedouble} 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 {@codestatic} {@link #valueOf(double)} method. * </ol> public BigDecimal(double val) { this(val,MathContext.UNLIMITED); }

第一段也说的很清楚它只能计算的无限接近这个数,但是无法精确到这个数。

第二段则说,如果要想准确计算这个值,那么需要把double类型的参数转化为String类型的。并且使用BigDecimal(String)这个构造方法进行构造。去获取结果。

正确运用BigDecimal

BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象,由刚才我们所罗列的API也可看出。

构建BigDecimal对象时,尽量使用BigDecimal(String)这个构造方法进行构造。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。