Java中使用Bigdecimal类型进行精确商业计算
2017-05-27 00:06
323 查看
java的float和double只能用来进行科学计算或工程计算,在大多数的商业计算中,一般采用java.math.BigDecimal类来进行精确计算。大数据类型 java.math.BigDecimal ,该类型的数据精度极高,适合做财务软件。
原因在于我们的计算机是二进制的。浮点数没有办法使用二进制进行精确表示。我们的CPU表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。如:2.4的二进制表示并非就是精确的2.4。反而最为接近的二进制表示是 2.3999999999999999。浮点数的值实际上是由一个特定的数学公式计算得到的。
BigDecimal中的舍入模式介绍:
舍入模式:RoundingMode中的舍入模式和BigDecimal中的舍入模式是一样的,比如RoundingMode.*相当于BigDecimal.ROUND_*
[b]ROUND_DOWN[/b] :向零方向舍入的舍入模式。从不对舍弃部分前面的数字加 1(即截尾)。注意,此舍入模式始终不会增加计算值的绝对值
[b]ROUND_FLOOR[/b] :向负无限大方向舍入的舍入模式。如果结果为正,则舍入行为类似于 RoundingMode.DOWN;如果结果为负,则舍入行为类似于 RoundingMode.UP。注意,此舍入模式始终不会增加计算值
[b]ROUND_UNNECESSARY[/b] :用于断言请求的操作具有精确结果的舍入模式,因此不需要舍入。如果对生成精确结果的操作指定此舍入模式,则抛出 ArithmeticException
[b]ROUND_UP[/b] :远离零方向舍入的舍入模式。始终对非零舍弃部分前面的数字加 1。注意,此舍入模式始终不会减少计算值的绝对值
[b]ROUND_HALF_DOWN[/b] :向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向下舍入。如果被舍弃部分 > 0.5,则舍入行为同 RoundingMode.UP;否则舍入行为同 RoundingMode.DOWN
[b]ROUND_HALF_EVEN[/b] :向 最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。如果舍弃部分左边的数字为奇数,则舍入行为同 RoundingMode.HALF_UP;如果为偶数,则舍入行为同 RoundingMode.HALF_DOWN。注意,在重复进行一系列计算时,此舍入模式可以在统计上将累加错误减到最小。此舍入模式也称为“银行家舍入法”,主要在美国使用。此舍入模式类似于 Java 中对 float 和 double 算法使用的舍入策略
[b]ROUND_HALF_UP[/b] :向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向上舍入。如果被舍弃部分 >= 0.5,则舍入行为同 RoundingMode.UP;否则舍入行为同 RoundingMode.DOWN。注意,此舍入模式就是通常学校里讲的四舍五入
工具类:
原因在于我们的计算机是二进制的。浮点数没有办法使用二进制进行精确表示。我们的CPU表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。如:2.4的二进制表示并非就是精确的2.4。反而最为接近的二进制表示是 2.3999999999999999。浮点数的值实际上是由一个特定的数学公式计算得到的。
BigDecimal中的舍入模式介绍:
舍入模式:RoundingMode中的舍入模式和BigDecimal中的舍入模式是一样的,比如RoundingMode.*相当于BigDecimal.ROUND_*
ROUND_CEILING :向正无限大方向舍入的舍入模式。如果结果为正,则舍入行为类似于 RoundingMode.UP;如果结果为负,则舍入行为类似于 RoundingMode.DOWN。注意,此舍入模式始终不会减少计算值
[b]ROUND_DOWN[/b] :向零方向舍入的舍入模式。从不对舍弃部分前面的数字加 1(即截尾)。注意,此舍入模式始终不会增加计算值的绝对值
[b]ROUND_FLOOR[/b] :向负无限大方向舍入的舍入模式。如果结果为正,则舍入行为类似于 RoundingMode.DOWN;如果结果为负,则舍入行为类似于 RoundingMode.UP。注意,此舍入模式始终不会增加计算值
[b]ROUND_UNNECESSARY[/b] :用于断言请求的操作具有精确结果的舍入模式,因此不需要舍入。如果对生成精确结果的操作指定此舍入模式,则抛出 ArithmeticException
[b]ROUND_UP[/b] :远离零方向舍入的舍入模式。始终对非零舍弃部分前面的数字加 1。注意,此舍入模式始终不会减少计算值的绝对值
[b]ROUND_HALF_DOWN[/b] :向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向下舍入。如果被舍弃部分 > 0.5,则舍入行为同 RoundingMode.UP;否则舍入行为同 RoundingMode.DOWN
[b]ROUND_HALF_EVEN[/b] :向 最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。如果舍弃部分左边的数字为奇数,则舍入行为同 RoundingMode.HALF_UP;如果为偶数,则舍入行为同 RoundingMode.HALF_DOWN。注意,在重复进行一系列计算时,此舍入模式可以在统计上将累加错误减到最小。此舍入模式也称为“银行家舍入法”,主要在美国使用。此舍入模式类似于 Java 中对 float 和 double 算法使用的舍入策略
[b]ROUND_HALF_UP[/b] :向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向上舍入。如果被舍弃部分 >= 0.5,则舍入行为同 RoundingMode.UP;否则舍入行为同 RoundingMode.DOWN。注意,此舍入模式就是通常学校里讲的四舍五入
工具类:
1 import java.math.BigDecimal; 2 3 public class BigDecimalUtil { 4 5 /** 6 * 提供精确加法计算的add方法 7 * @param value1 被加数 8 * @param value2 加数 9 * @return 两个参数的和 10 */ 11 public static double add(double value1,double value2){ 12 BigDecimal b1 = new BigDecimal(Double.valueOf(value1)); 13 BigDecimal b2 = new BigDecimal(Double.valueOf(value2)); 14 return b1.add(b2).doubleValue(); 15 } 16 17 /** 18 * 提供精确减法运算的sub方法 19 * @param value1 被减数 20 * @param value2 减数 21 * @return 两个参数的差 22 */ 23 public static double sub(double value1,double value2){ 24 BigDecimal b1 = new BigDecimal(Double.valueOf(value1)); 25 BigDecimal b2 = new BigDecimal(Double.valueOf(value2)); 26 return b1.subtract(b2).doubleValue(); 27 } 28 29 /** 30 * 提供精确乘法运算的mul方法 31 * @param value1 被乘数 32 * @param value2 乘数 33 * @return 两个参数的积 34 */ 35 public static double mul(double value1,double value2){ 36 BigDecimal b1 = new BigDecimal(Double.valueOf(value1)); 37 BigDecimal b2 = new BigDecimal(Double.valueOf(value2)); 38 return b1.multiply(b2).doubleValue(); 39 } 40 41 /** 42 * 提供(相对)精确的除法运算div方法,当发生除不尽的情况时,由 scale 参数指定精度,其后的数字四舍五入。 43 * @param value1 被除数 44 * @param value2 除数 45 * @param scale 精确范围,小数点后保留几位 46 * @return 两个参数的商 47 * @throws IllegalAccessException 48 */ 49 public static double div(double value1,double value2,int scale) throws IllegalAccessException{ 50 //如果精确范围小于0,抛出异常信息 51 if(scale < 0){ 52 throw new IllegalAccessException("精确度不能小于0"); 53 } 54 BigDecimal b1 = new BigDecimal(Double.valueOf(value1)); 55 BigDecimal b2 = new BigDecimal(Double.valueOf(value2)); 56 return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); 57 } 58 59 /** 60 * 提供精确的小数位四舍五入处理。 61 * @param value 需要四舍五入的数字 62 * @param scale 精确范围,小数点后保留几位 63 * @return 四舍五入后的结果 64 * @throws IllegalAccessException 65 */ 66 public static double round(double value, int scale) throws IllegalAccessException{ 67 //如果精确范围小于0,抛出异常信息 68 if(scale<0){ 69 throw new IllegalAccessException("精确度不能小于0"); 70 } 71 BigDecimal b = new BigDecimal(Double.toString(value)); 72 BigDecimal one = new BigDecimal("1"); 73 return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); 74 } 75 76 }
相关文章推荐
- Java使用BigDecimal进行精确计算
- Java中使用BigDecimal进行浮点数精确计算、超大整数、浮点数等计算,没有数位限制
- Java中使用BigDecimal进行浮点数精确计算、超大整数、浮点数等计算,没有数位限制
- Java中使用BigDecimal进行浮点数精确计算、超大整数、浮点数等计算,没有数位限制
- Java中使用BigDecimal进行浮点数精确计算、超大整数、浮点数等计算,没有数位限制
- 使用BigDecimal对象进行Java浮点数精确计算
- Java中使用BigDecimal进行浮点数精确计算、超大整数、浮点数等计算,没有数位限制
- Java中使用BigDecimal进行浮点数精确计算、超大整数、浮点数等计算
- Java使用BigDecimal进行高精度计算的示例代码
- Java使用BigDecimal解决精确计算的问题
- Java基础----使用BigDecimal进行精确运算
- java 金额计算,商业计算 double不精确问题 BigDecimal,Double保留两位小数方法
- Java中使用BigDecimal进行浮点数高精度计算
- Java中使用BigDecimal进行精确运算
- 电商网站中价格的精确计算(使用BigDecimal进行精确运算(实现加减乘除运算))
- 使用BigDecimal进行精确小数计算
- Java使用BigDecimal精确计算的简单公式计算器
- Java使用BigDecimal精确计算的简单公式计算器
- Java BigDecimal进行精确计算
- Java中double类型计算不精确的解决办法(BigDecimal)