`
yznxing
  • 浏览: 367196 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

BigDecimal带精度的运算

    博客分类:
  • java
阅读更多

 

     之前提到过在商业运算中要使用BigDecimal来进行相关的钱的运算(java中关于浮点运算需要注意的 ),可是实际使用中,简单的用BigDecimal还是出现了一些小问题。

 

        BigDecimal a = new BigDecimal(998.01);
        BigDecimal b=new BigDecimal("100");
        System.out.println(a.multiply(b));
        
        BigDecimal aa = new BigDecimal(135.95);
        BigDecimal bb=new BigDecimal("100");
        System.out.println(aa.multiply(bb));
        
        
        BigDecimal test = new BigDecimal(4.015);
        BigDecimal test1 = new BigDecimal(100);
        System.out.println(test.multiply(test1));
 

输出结果为:

 

99800.999999999999090505298227071762084960937500
13594.99999999999886313162278383970260620117187500
401.49999999999996802557689079549163579940795898437500

 

   出现这种情况的原因就是没有使用BigDecimal的精度。不罗嗦了,直接写上使用BigDecimal的带精度的运算。

 

   比较简单,看代码:

 

 

BigDecimal aa = new BigDecimal(135.95);
BigDecimal bb=new BigDecimal("100");
BigDecimal result=aa.multiply(bb);
System.out.println(result.setScale(2,BigDecimal.ROUND_HALF_EVEN));
 

    此时的输出结果为:

 

13595.00
 

    最主要的是运用了:

 

 

result.setScale(2,BigDecimal.ROUND_HALF_EVEN)

 

    看一下BigDecimal的setScale的api

 

 

BigDecimal的API 写道
可以通过两种类型的操作来处理 BigDecimal 的标度:标度/舍入操作和小数点移动操作。标度/舍入操作(setScale 和 round)返回 BigDecimal,其值近似地(或精确地)等于操作数的值,但是其标度或精度是指定的值;即:它们会增加或减少对其值具有最小影响的存储数的精度。小数点移动操作(movePointLeft 和 movePointRight)返回从操作数创建的 BigDecimal,创建的方法是按指定方向将小数点移动一个指定距离。

 

 

setScale

public BigDecimal setScale(int newScale,
                           int roundingMode)
返回一个 BigDecimal,其标度为指定值,其非标度值通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定,
以维护其总值。如果该操作减少标度,则非标度值必须被除(而不是乘),并且该值可以更改;在这种情况下,将指定的
舍入模式应用到除法中。
注意,由于 BigDecimal 对象是不可变的,此方法的调用不会 导致初始对象被修改,
这与使用名为 setX 变异字段 X 方法的常规约定相反。相反,setScale 返回具有适当标度的对象;
返回的对象不一定是新分配的。

相对于此遗留方法,应优先使用新的 setScale(int, RoundingMode) 方法。

参数:
newScale - 要返回的 BigDecimal 值的标度。
roundingMode - 要应用的舍入模式。
返回:
一个 BigDecimal,其标度为指定值,其非标度值可以通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定。

RoundingMode的API

 

 

枚举常量摘要
CEILING  
          向正无限大方向舍入的舍入模式。
DOWN  
          向零方向舍入的舍入模式。
FLOOR  
          向负无限大方向舍入的舍入模式。
HALF_DOWN  
          向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向下舍入。
HALF_EVEN  
          向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
HALF_UP  
          向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向上舍入。
UNNECESSARY  
          用于断言请求的操作具有精确结果的舍入模式,因此不需要舍入。
UP  
          远离零方向舍入的舍入模式。

 

 

  看完这些前面那个:

 

result.setScale(2,BigDecimal.ROUND_HALF_EVEN)

 

   的意思就是,将这个BigDecimal小数点后保留2位,四舍五入的方式为向最接近数字方向舍入的舍入 模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。

 

    ok,记录完毕,看来以后要用bigDecimal还必须要用它这个scale的功能来保证精度,不然还是跟double一样会出现悲剧!

 

 

 

 

 

 

5
4
分享到:
评论
5 楼 xujishen 2016-09-22  
新入职 写道
还是没很明白~~这个BigDecimal.ROUND_HALF_EVEN的意思,感觉像文字游戏似的...语文不好啊

----------
even的意思就是  四舍六如 逢 五 上双: .4 以下肯定舍, .6 以上肯定入.  .5 往偶数那个方向舍入.
所以 3.5 和 4.5 都会舍入到 偶数 4  上面!
4 楼 jinianjun 2015-07-26  
楼主请看看chenem2000同学的回复。真实问题被你掩盖了。
3 楼 Ripin_Yan 2015-04-30  
楼主有点小疑问,BigDecimal.ROUND_HALF_EVEN方式可不是四舍五入,比如8.15,scale=1,那么结果就是8.2;但是8.25运算后还是8.2。四舍五入的应该是BigDecimal.ROUND_HALF_UP
2 楼 chenem2000 2011-04-13  
1.BigDecimal a = new BigDecimal(998.01);  
这样用double 构造BigDecimal是不精确的,因为double在计算机的表示本身就是不精确的。其实在java文档里的这个构造方法也提到:
Notes:

The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a 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 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.
The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal("0.1") creates a BigDecimal which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the String constructor be used in preference to this one.
When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor. To get that result, use the static valueOf(double) method.

所以应该用string去构造浮点数。
BigDecimal a = new BigDecimal("998.01"); 
BigDecimal b=new BigDecimal("100"); 
System.out.println(a.multiply(b));
这样的结果就是99801.00。
当然我们仍然可以设定精度,特别是在除法的情况下。
1 楼 新入职 2010-08-17  
还是没很明白~~这个BigDecimal.ROUND_HALF_EVEN的意思,感觉像文字游戏似的...语文不好啊

相关推荐

    BigDecimal 加减乘除运算

    Java中BigInteger的数学运算,BigDecimal 加减乘除运算,Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大...

    高精度JSBigDecimal运算

    高精度JSBigDecimal运算,解决JS中BigDecimal运算和精度问题。

    DecimalFormat精度解决,商业运算精度问题

    DecimalFormat精度解决,商业运算精度问题,BigDecimal类的应用--------------

    大精度的数学运算

    大精度的数学运算,通过BigDecimal来实现了加、减、乘、除与四舍五入运算。

    Bigdecimal.js

    是不是还在为多精度小数运算烦恼 这个满足你一切要求 项目中需要对金钱进行运算,为了使计算结果更准确,故使用bigDecimal工具来实现

    bignumber.min.js下载

    众所周知,数字运算的精度问题是一个让人很旦疼的问题,而java中有BigDecimal类对数字精度问题进行处理,经过一番查询,发现前段有一个宝藏精度处理类bignumber。亲测好用。 众所周知,数字运算的精度问题是一个让人...

    javaInteger大数据运算.pdf

    //BigDecimal ⾼精度⼩数运算 BigDecimal b3=new BigDecimal("0.09"); BigDecimal b4=new BigDecimal("0.01"); //加法 System.out.println(b3.add(b4)); //减法 System.out.println(b3.subtract(b4)); //乘法 ...

    Java的数学运算处理类讲解代码(BigDecimal、Math、Random、DecimalFormat类全部操作方法API)

    理解BigDecimal类的使用,并了解如何处理大数精度计算和避免精度丢失。 掌握Math类提供的各种数学计算方法,如三角函数、指数运算等。 学习Random类的使用,包括生成随机数和调整范围。 理解DecimalFormat类的功能,...

    bigDecimal.js

    JavaScript解决高精度数字运算。

    bigdecimal.js

    在前端实际开发中,进行前端计算会出现丢失精度的问题,项目中需要对金钱进行运算,为了使计算结果更准确,故使用bigDecimal工具来实现

    JS小数加减乘除运算后位数增加的解决方案

    JS小数加减乘除运算后小数点后产生多位数和计算精度损失的解决方案

    带括号高精度计算器

    实现带括号的简单计算器,能够进行10000位的运算,支持大整数开方。不过,点击关闭窗口按钮时有时候不能关闭,请大家帮忙看看,另外,大数开方是用c++封装的dll。

    ArithmeticUtils用于高精确处理常用的数学运算工具类

    ArithmeticUtils用于高精确处理常用的数学运算工具类 提供精确的加法运算 提供精确的减法运算 ...当发生除不尽的情况时,由scale参数指定精度,以后的数字四舍五入 提供精确的小数位四舍五入处理 取余数 比较大小

    BigDecimal:具有任意精度的十进制数的算术和演算。-开源

    在BigDecimal中,所有的算术运算都被实现,包括对数,线性方程组的系统解析度,三角函数,多项式回归,双曲函数,臭名昭著的伽马函数(非整数实数的阶乘)以及将继续实现的更多函数。 我的意图是至少实现Windows...

    Java中double类型下出现精度计算错误情况下出力方法

     要保证精度就要使用BigDecimal类,而且不能直接从double直接转BigDecimal,要将double转string再转BigDecimal。也就是不能使用BigDecimal(double val) 方法,你会发现没有效果。要使用BigDecimal(String val) 方法...

    Java 加减乘除工具类(解决精度损失问题)

    //精度为2,舍入模式为大于0.5进1,否则舍弃 BigDecimal b1 = new BigDecimal(Double.toString(value1.doubleValue())); BigDecimal b2 = new BigDecimal(Double.toString(value2.doubleValue())); return b1....

    Singulink.Numerics.BigDecimal:全功能支持任意精度的十进制值

    Singulink.Numerics.BigDecimal BigDecimal是功能齐全的十进制类型,支持任意大的精度值。 它具有您希望从完整实现中获得的所有数学运算符,字符串转换和解析功能(具有完整的NumberStyles支持),并且针对所有大小...

    c++ 无符号高精度bigint

    无符号的bigint高精度大整数类,包含基本比较和运算,支持流式输入输出!

    java中BigDecimal进行加减乘除的基本用法

    大家应该对于不需要任何准确计算精度的数字可以直接使用float或double运算,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数的操作。下面这篇文章就给大家介绍介绍关于...

    BigDecimalUtils

    Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做...

Global site tag (gtag.js) - Google Analytics