`

BigDecimal讲解

    博客分类:
  • java
阅读更多
BigDecimal 由任意精度的整数非标度值 和 32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负 scale 次幂。因此,BigDecimal 表示的数值是 (unscaledValue × 10-scale)。

可以处理任意长度的浮点数运算。

BigDecimal add(BigDecimal val) //BigDecimal 加法

BigDecimal subtract (BigDecimal val) //BigDecimal 减法

BigDecimal multiply (BigDecimal val)  //BigDecimal 乘法

BigDecimal divide (BigDecimal val,RoundingMode mode)  除法


具体使用 计算:

  
  加:   a.add(b);

  减: a.subtract(b);

  乘:   a.multiply(b);

  除:   a.divide(b,2);//2为精度取值
除法细解:
  //注意以下相除会抛出异常,原因: 通过BigDecimal的divide方法进行除法时当不整除,出现无限循环小数时,就会抛异常 
        //BigDecimal divideBg = a.divide(b);  
        //解决方法是:设置精确度;就是给divide设置精确的小数点
divide(xxxxx,2, BigDecimal.ROUND_HALF_EVEN)  
        //其中的第二个参数表示的是:保留小数点之后多少位 

BigDecimal不整除抛出的异常,请设置精确度!
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1278)
at main.Main.main(Main.java:41)

下面我们来看看除法的详细说明:
   divide(BigDecimal divisor, int scale, introundingMode)


BigDecimal的setScale方法

BigDecimal.setScale()

方法用于格式化小数点

表示保留一位小数,默认用四舍五入方式

setScale(1)

直接删除多余的小数位,如2.35会变成2.3 setScale(1,BigDecimal.ROUND_DOWN)

进位处理,2.35变成2.4  setScale(1,BigDecimal.ROUND_UP)

四舍五入,2.35变成2.4  setScale(1,BigDecimal.ROUND_HALF_UP)

四舍五入,2.35变成2.3,如果是5则向下舍setScaler(1,BigDecimal.ROUND_HALF_DOWN)

 
注意点一

scale指的是你小数点后的位数。
scale()就是BigDecimal类中的方法。如

BigDecimal b = new BigDecimal("123.456");

b.scale()返回的就是3
注意点二roundingMode是小数的保留模式。它们都是BigDecimal中的常量字段,

有很多种,如
BigDecimal.ROUND_HALF_UP表示的就是4舍5入

注意点三

divide(BigDecimal divisor, int scale, introundingMode)的意思是说:
我用一个BigDecimal对象除以divisor后的结果,并且要求这个结果保留有scale个小数位,roundingMode表示的就是保留模式是什么,是四舍五入啊还是其它的


BigDecimal aa = new  BigDecimal(135.95 ); 

BigDecimal bb=new  BigDecimal("100" ); 

BigDecimal result=aa.multiply(bb);  //做加法



3.java中 BigDecimal类型的可以转换到double类型:
  用 变量.doubleValue();函数  即可将 BigDecimal 类型数据 转化为 double类型!
4.java BigDecimal比较大小

可以通过BigDecimal的compareTo方法来进行比较。
返回的结果是int类型,-1表示小于,0是等于,1是大于。

看下面这个例子:
BigDecimal a = new BigDecimal("1.00");
BigDecmial b = new BigDecimal(1);

想比较一下a和b的大小,一般都会用equals

System.out.println(a.equals(b));
但是输出结果是:false
原因是:BigDecimal比较时,不仅比较值,而且还比较精度?


if(a.compareTo(b)==0) 结果是true

比较大小可以用 a.compareTo(b)
返回值    -1 小于   0 等于    1 大于

5.BigDecimal取其中最大、最小值、绝对值、相反数:

  a.max (b) //比较取最大值

  a.min(b) //比较取最小值

  a.abs()//取最绝对值

  a.negate()//取相反数


6.下面是注意 :

BigDecimal枚举常量用法摘要  :

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



7.关于BigDecimal格式化

public String formatValue(Object value){
        String content = null;
        if (value == null) {
             content = "";
         } else {
             if(value instanceof BigDecimal){
                 //conver to fortmat String
                 NumberFormat nf = NumberFormat.getInstance();
                 nf.setMinimumFractionDigits(2);
                 nf.setMaximumFractionDigits(2);
                 content = nf.format(value); 
             }else{
                 content = String.valueOf(value);
             }
         }
        return content;
    }

使用这样一个方法可以达到格式化的效果,其中value instanceof BigDecimal,表示的是字符类型是BigDecimal类型的时候执行,这里的NumberFormat就表示字符类型,下面的两句代码就表示小数点后面的精确位数。

这里还要提到NumberFormat的其他两个类型:

getCurrencyInstance(): 返回当前默认 环境的货币格式

CurrencyInstance(): 返回指定语言 环境的数字格式,一般是百分比格式


8.在《Effective Java》这本书中也提到这个原则,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用java.math.BigDecimal。
我们如果需要精确计算,非要用String来够造BigDecimal不可!

下面的这个工具类是是转载别人的,可以通过个工具类实现小数的精确计算。

1import java.math.BigDecimal;  
2/** *//** 
3* 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精 
4* 确的浮点数运算,包括加减乘除和四舍五入。 
5*/ 
6public class Arith{  
7    //默认除法运算精度  
8    private static final int DEF_DIV_SCALE = 10;  
9    //这个类不能实例化  
10    private Arith(){  
11    }  
12 
13    /** *//** 
14     * 提供精确的加法运算。 
15     * @param v1 被加数 
16     * @param v2 加数 
17     * @return 两个参数的和 
18     */ 
19    public static double add(double v1,double v2){  
20        BigDecimal b1 = new BigDecimal(Double.toString(v1));  
21        BigDecimal b2 = new BigDecimal(Double.toString(v2));  
22        return b1.add(b2).doubleValue();  
23    }  
24    /** *//** 
25     * 提供精确的减法运算。 
26     * @param v1 被减数 
27     * @param v2 减数 
28     * @return 两个参数的差 
29     */ 
30    public static double sub(double v1,double v2){  
31        BigDecimal b1 = new BigDecimal(Double.toString(v1));  
32        BigDecimal b2 = new BigDecimal(Double.toString(v2));  
33        return b1.subtract(b2).doubleValue();  
34    }   
35    /** *//** 
36     * 提供精确的乘法运算。 
37     * @param v1 被乘数 
38     * @param v2 乘数 
39     * @return 两个参数的积 
40     */ 
41    public static double mul(double v1,double v2){  
42        BigDecimal b1 = new BigDecimal(Double.toString(v1));  
43        BigDecimal b2 = new BigDecimal(Double.toString(v2));  
44        return b1.multiply(b2).doubleValue();  
45    }  
46 
47    /** *//** 
48     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 
49     * 小数点以后10位,以后的数字四舍五入。 
50     * @param v1 被除数 
51     * @param v2 除数 
52     * @return 两个参数的商 
53     */ 
54    public static double div(double v1,double v2){  
55        return div(v1,v2,DEF_DIV_SCALE);  
56    }  
57 
58    /** *//** 
59     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 
60     * 定精度,以后的数字四舍五入。 
61     * @param v1 被除数 
62     * @param v2 除数 
63     * @param scale 表示表示需要精确到小数点以后几位。 
64     * @return 两个参数的商 
65     */ 
66    public static double div(double v1,double v2,int scale){  
67        if(scale<0){  
68            throw new IllegalArgumentException(  
69                "The scale must be a positive integer or zero");  
70        }  
71        BigDecimal b1 = new BigDecimal(Double.toString(v1));  
72        BigDecimal b2 = new BigDecimal(Double.toString(v2));  
73        return b1.divid(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();  
74    }  
75 
76    /** *//** 
77     * 提供精确的小数位四舍五入处理。 
78     * @param v 需要四舍五入的数字 
79     * @param scale 小数点后保留几位 
80     * @return 四舍五入后的结果 
81     */ 
82    public static double round(double v,int scale){  
83        if(scale<0){  
84            throw new IllegalArgumentException(  
85                "The scale must be a positive integer or zero");  
86        }  
87        BigDecimal b = new BigDecimal(Double.toString(v));  
88        BigDecimal one = new BigDecimal("1");  
89        return b.divid(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();  
90     }  
91  } 


详细BigDecimal 算法请参考 http://zhenchengchagangzi.iteye.com/blog/1258453




Java中BigDecimal的8种舍入模式:

java.math.BigDecimal
不可变的、任意精度的有符号十进制数。BigDecimal 由任意精度的整数非标度值和32位的整数标度(scale)组成。
如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以10的负scale次幂。
因此,BigDecimal表示的数值是(unscaledValue × 10-scale)。
与之相关的还有两个类:
java.math.MathContext:
该对象是封装上下文设置的不可变对象,它描述数字运算符的某些规则,如数据的精度,舍入方式等。
java.math.RoundingMode:
这是一种枚举类型,定义了很多常用的数据舍入方式。
这个类用起来还是很比较复杂的,原因在于舍入模式,数据运算规则太多太多,
不是数学专业出身的人看着中文API都难以理解,这些规则在实际中使用的时候在翻阅都来得及。
在银行、帐户、计费等领域,BigDecimal提供了精确的数值计算。其中8种舍入方式值得掌握。
1、ROUND_UP
舍入远离零的舍入模式。
在丢弃非零部分之前始终增加数字(始终对非零舍弃部分前面的数字加1)。
注意,此舍入模式始终不会减少计算值的大小。
2、ROUND_DOWN
接近零的舍入模式。
在丢弃某部分之前始终不增加数字(从不对舍弃部分前面的数字加1,即截短)。
注意,此舍入模式始终不会增加计算值的大小。
3、ROUND_CEILING
接近正无穷大的舍入模式。
如果 BigDecimal 为正,则舍入行为与 ROUND_UP 相同;
如果为负,则舍入行为与 ROUND_DOWN 相同。
注意,此舍入模式始终不会减少计算值。
4、ROUND_FLOOR
接近负无穷大的舍入模式。
如果 BigDecimal 为正,则舍入行为与 ROUND_DOWN 相同;
如果为负,则舍入行为与 ROUND_UP 相同。
注意,此舍入模式始终不会增加计算值。
5、ROUND_HALF_UP
向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。
如果舍弃部分 >= 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。
注意,这是我们大多数人在小学时就学过的舍入模式(四舍五入)。
6、ROUND_HALF_DOWN
向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式。
如果舍弃部分 > 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同(五舍六入)。
7、ROUND_HALF_EVEN
向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同;
如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。
注意,在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。
此舍入模式也称为“银行家舍入法”,主要在美国使用。四舍六入,五分两种情况。
如果前一位为奇数,则入位,否则舍去。
以下例子为保留小数点1位,那么这种舍入方式下的结果。
1.15>1.2 1.25>1.2
8、ROUND_UNNECESSARY
断言请求的操作具有精确的结果,因此不需要舍入。
如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。

不同舍入模式下的舍入操作汇总
根据给定的舍入模式将输入数字舍入为一位数的结果
输入数字 UP DOWN CEILING FLOOR HALF_UP HALF_DOWN HALF_EVEN UNNECESSARY
5.5 6 5 6 5 6 5 6 抛出 ArithmeticException
2.5 3 2 3 2 3 2 2 抛出 ArithmeticException
1.6 2 1 2 1 2 2 2 抛出 ArithmeticException
1.1 2 1 2 1 1 1 1 抛出 ArithmeticException
1.0 1 1 1 1 1 1 1 1
-1.0 -1 -1 -1 -1 -1 -1 -1 -1
-1.1 -2 -1 -1 -2 -1 -1 -1 抛出 ArithmeticException
-1.6 -2 -1 -1 -2 -2 -2 -2 抛出 ArithmeticException
-2.5 -3 -2 -2 -3 -3 -2 -2 抛出 ArithmeticException
-5.5 -6 -5 -5 -6 -6 -5 -6 抛出 ArithmeticException


转载自:
http://zhangyinhu8680.iteye.com/blog/1536397
http://www.bdqn.cn/news/201311/11834.shtml








分享到:
评论

相关推荐

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

    这个源码资源是一个讲解数学计算处理类的示例项目,旨在帮助开发者理解和使用Java中的数学计算相关类库。该项目包含详细的代码示例和注释,涵盖了以下几个主要的数学计算处理类:BigDecimal、Math、Random和...

    《深入浅出struts》 源代码

    源代码通常包含了书中所讲解的实际应用示例,便于读者理解和学习。 在提供的压缩包文件中,我们可以看到以下内容: 1. **win-compile.bat** 和 **linux-compile.sh**:这两个文件分别对应Windows和Linux平台的编译...

    大数相加 java

    本篇文章将详细讲解如何在Java中实现大数相加,同时考虑异常处理和代码的可拓展性。 首先,Java标准库提供了一个名为`BigInteger`的类,用于处理任意精度的大整数。但是,为了理解基本的算法和提升编程能力,我们...

    长方形和正方形的周长jsp(1).ppt

    这里,我们以“长方形和正方形的周长”为主题,讲解相关数学概念及其在实际编程中的应用。 周长是几何学中的基本概念,指的是封闭图形边缘的总长度。对于三角形,其周长等于三边之和;对于四边形,周长则是四条边的...

    不同中奖概率产生中奖人

    以下将详细讲解如何利用Java来构建这样的系统。 首先,我们来看`LotteryProp.java`和`Lottery.java`这两个文件。`LotteryProp.java`可能包含了中奖概率的类定义,而`Lottery.java`则可能实现了抽奖逻辑。在`...

    IBM-ETP-java培训09.Java 常用类讲解.ppt

    7. **java.math**: 提供了大整数(`BigInteger`)和大浮点数(`BigDecimal`)的处理,适用于需要高精度计算的场景。 在IBM的ETP培训课程中,会深入讲解这些类的使用方法、特性以及最佳实践。通过学习,开发者不仅能...

    java 基础知识+附加代码讲解汇总Day02

    此外,通过附加代码讲解和示例,可以加深对知识的理解,并学会如何将理论知识应用到实践中。学习Java基础知识并不仅仅是记住概念和语法,更重要的是要通过编写代码来加深记忆和理解。通过不断的练习,可以逐渐熟练地...

    Java核心技术介绍-java核心技术讲解word格式可编辑.docx

    BigDecimal bg = new BigDecimal(f); double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); System.out.println(f1); } public void method2() { DecimalFormat df = new DecimalFormat("#....

    dwr详细配置说明和讲解

    - `BigNumberConverter`:处理大数字,如BigInteger和BigDecimal。 除了这些,DWR还提供了如`BeanConverter`和`MapConverter`等高级转换器,用于处理更复杂的对象结构。 配置DWR时,需要注意安全性和性能。由于DWR...

    人民币小写转大写JAVA程序.doc

    本文档主要讲解了使用JAVA程序将人民币小写转换为大写的实现方法。该程序使用了BigDecimal类型来处理金额,并使用String数组来存储中文数字和单位。 知识点1:BigDecimal类型在JAVA中的应用 在JAVA中,BigDecimal...

    java编译的大整数程序可加减求绝对值开平方

    本文将详细讲解如何使用`BigInteger`进行大整数的加减运算、求绝对值以及开平方。 1. ** BigInteger 类的创建与使用**: `BigInteger`类通过构造函数创建,可以接受字符串或者字节数组作为参数。例如,创建一个大...

    Java实现大数运算的实例代码

    下面将对Java实现大数运算的实例代码进行详细的讲解。 一、大数运算介绍 大数运算,顾名思义,就是很大的数值的数进行一系列的运算。它是指由于编程语言提供的基本数值数据类型表示的数值范围有限,不能满足较大...

    数字格式化类与大数处理利用案例轻松学习Java语言PPT学习教案.pptx

    本篇内容主要讲解了Java中的`NumberFormat`类和`DecimalFormat`类用于数字格式化,以及`BigInteger`和`BigDecimal`类用于大数处理。 `NumberFormat`类是Java `java.text`包中的一个抽象类,它提供了对数字进行格式...

    Drools开发最全中文版技术指南

    《Drools开发最全中文版技术指南》是一份针对Java开发者的重要参考资料,它全面讲解了如何使用Drools这一强大的规则引擎进行业务逻辑的构建和管理。Drools是Red Hat公司推出的一个开源规则引擎,它基于Java,支持...

    java数组的初始化及操作详解

    数组的初始化和操作是 Java 编程的基础知识,本文将对 Java 数组的初始化和操作进行详细的讲解。 一、数组的基本概念 数组是一组相关类型的变量集合,并且这些变量可以按照统一的方式进行操作。数组本身属于引用...

    Java.7.Recipes

    它覆盖了Java中各种数值类型的使用,包括整型、浮点型和大数类型(`BigInteger`和`BigDecimal`)。同时,也讲解了新的日期时间API(`java.time`包),提供了创建、解析、格式化日期时间的方法。 ### 第4章:数据...

    Java常用API

    本课程是《零基础学Java》课程的第六阶段课程,课程内容详实、细致,讲解通俗易懂!本课程采用Eclipse4.9版本进行教学。内容包括以下常用JavaAPI的...6.BigInteger类/BigDecimal类 7.Date类/DateFormat类/Calendar类

    java金钱处理方法实例详解

    本篇将深入讲解Java中金钱处理方法,特别是如何将分转化为元。 在Java中,通常使用BigDecimal类来处理货币数据,因为它可以提供精确的浮点数运算。BigDecimal对象不直接存储浮点数,而是通过一个字符串表示,并且...

    JAVA课件 java 程序设计

    此外,可能会涉及数值运算,如大数运算(BigInteger和BigDecimal)和随机数生成。 7. **第7章 AWT组件与事件处理**:最后,进入GUI编程领域,AWT(Abstract Window Toolkit)是Java早期的图形用户界面库。这一章会...

    java计算机学习,廖雪峰教程,如果侵权,联系我删除;廖雪峰教程.pdf

    4. Java核心类:讨论了字符串和编码(StringBuilder、StringJoiner)、包装类型(如BigInteger、BigDecimal)、JavaBean、枚举类以及常用工具类。 5. 异常处理:包括Java的异常捕获机制、自定义异常、使用断言以及...

Global site tag (gtag.js) - Google Analytics