[置顶] Java-BigDecimal 分析


引言

  最近在看项目中的各种计算,由于是金融方面的项目,触及到日化,年化,利息,债转这些和钱有关的计算很多,其中全部通过BigDecimal类进行的运算,之前触及到的计算基本都用+、-、*、/等算术运算符直接进行数学运算,数据类型1般用double就可以解决问题,但是如果要求完全精度时double就不适合了,由于double是在广域数值范围上提供较为精确的快速近似计算(只能处理16位有效数)。

  BigDecimalJavajava.math包中提供的API类,主要用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际利用中,需要对更大或更小的数进行运算和处理。floatdouble只能用来做科学计算或是工程计算,在商业计算中要java.math.BigDecimal

  BigDecimal所创建的是对象,我们不能使用传统的+*/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。下面来看BigDecimal的构造方法。

 

构造方法

  BigDecimal(int)创建1个具有参数所指定整数值的对象。

  BigDecimal(double)创建1个具有参数所指定双精度值的对象。

  BigDecimal(long)创建1个具有参数所指定长整数值的对象。

  BigDecimal(String)创建1个具有参数所指定以字符串表示的数值的对象。

 

 这里需要注意的是double类型的,先看1个实例:

<pre name="code" class="java">//1、BigDecimal(double)
BigDecimal aDouble =new BigDecimal(1.1);
System.out.println("to double: " + aDouble);

// 2、BigDecimal(String)
BigDecimal aString = new BigDecimal("1.1");
System.out.println("to string: " + aString);

//3、BigDecimal.valueOf(double)
BigDecimal aValue = BigDecimal.valueOf(1.1);
System.out.println("valueOf: " + aValue);


 输出结果:

to double: 1.100000000000000088817841970012523233890533447265625
to string: 1.1
valueOf: 1.1

 

 1、这里我们注意到参数为double类型是,构造的BigDecimal值实际上等于1.100000000000000088817841970012523233890533447265625,而不是1.1,这是由于1.1没法准确地表示为double(或说对该情况,不能表示为任何有限长度的2进制小数)。

 2、参数为String类型构造的BigDecimal值正好等于原值1.1。因此,在我们构造BigDecimal值时通常选择参数为String类型的构造方法。

 3、当double 必须用作BigDecimal的参数时,可以先使用Double.toString(double)方法将double转换为String,然后使用BigDecimal(String)构造方法。再使用BigDecimal.valueOf(double)方法获得值。

 

运算方式

  加减乘除最基本的运算

  BigDecimal add(BigDecimal augend) 加法运算

  BigDecimal subtract(BigDecimal subtrahend) 减法运算

  BigDecimal multiply(BigDecimal multiplicand) 乘法运算

  BigDecimal divide(BigDecimal divisor) 除法运算

  由于寻求高精度,我们使用BigDecimal,但是在进行带除法的运算时,并且结果需要保存有效位数的时,可能会出现精度问题。那甚么时候会出现呢?

  我们知道10除3是永久除不尽的,并且结果我们需要进行格式化(保存有效位数)

 

精度和保存模式

  BigDecimal对象的精度没有限制。对除不尽的除法运算,比如10/3,divide方法将会抛出 java.lang.ArithmeticException毛病,所以除法运算要尽可能使用divide(BigDecimal d, int scale, int roundMode)指定标度和保存模式来避免异常。

scale,标度,小数点保存的位数

roundMode,保存模式

BigDecimal.ROUND_DOWN:直接丢掉标度之外的小数

BigDecimal.ROUND_UP:不管舍弃的小数是几,都进1

BigDecimal.ROUND_HALF_UP:最多见的4舍5入

还有其他的模式,可以直接去源码里看。

来看实例计算:

<pre name="code" class="java">BigDecimal a =new BigDecimal("10");
BigDecimal c = a.divide(new BigDecimal(3),10,BigDecimal.ROUND_DOWN);
BigDecimal d = c.multiply(new BigDecimal(3));
System.out.println("value: " + c);
System.out.println("value: " + d);


输出结果为:

value: 3.3333333333
value: 9.9999999999

由于第1步的除法指定了标度和保存模式,我们得到的是1个近似值,已丢失了精度,在进行后续的运算中,精度已没法保证,如何解决这类问题?应当把除法运算放在全部运算的最后,以减小除法带来的精度问题。

总结

  商业计算对钱最敏感,1分1毫平时看来很小,但是放在million,billion中,every
hundred损失a cent,结果也是巨大的。学习亦是如此,每天学习1分,1年后取得的改变也是巨大的。

波比源码 – 精品源码模版分享 | www.bobi11.com
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!

波比源码 » [置顶] Java-BigDecimal 分析

发表评论

Hi, 如果你对这款模板有疑问,可以跟我联系哦!

联系站长
赞助VIP 享更多特权,建议使用 QQ 登录
喜欢我嘛?喜欢就按“ctrl+D”收藏我吧!♡