zoukankan      html  css  js  c++  java
  • BigDecimal带精度的运算的两篇文章

    转自:http://guoliangqi.iteye.com/blog/670908

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

    Java代码  收藏代码
    1. BigDecimal a = new BigDecimal(998.01);  
    2. BigDecimal b=new BigDecimal("100");  
    3. System.out.println(a.multiply(b));  
    4.   
    5. BigDecimal aa = new BigDecimal(135.95);  
    6. BigDecimal bb=new BigDecimal("100");  
    7. System.out.println(aa.multiply(bb));  
    8.   
    9.   
    10. BigDecimal test = new BigDecimal(4.015);  
    11. BigDecimal test1 = new BigDecimal(100);  
    12. System.out.println(test.multiply(test1));  

     

    输出结果为:

    Java代码  收藏代码
    1. 99800.999999999999090505298227071762084960937500  
    2. 13594.99999999999886313162278383970260620117187500  
    3. 401.49999999999996802557689079549163579940795898437500  

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

       比较简单,看代码:

    Java代码  收藏代码
    1. BigDecimal aa = new BigDecimal(135.95);  
    2. BigDecimal bb=new BigDecimal("100");  
    3. BigDecimal result=aa.multiply(bb);  
    4. System.out.println(result.setScale(2,BigDecimal.ROUND_HALF_EVEN));  

     

        此时的输出结果为:

    Java代码  收藏代码
    1. 13595.00  

     

        最主要的是运用了:

    Java代码  收藏代码
    1. result.setScale(2,BigDecimal.ROUND_HALF_EVEN)  

        看一下BigDecimal的setScale的api

    BigDecimal的API 写道
    可以通过两种类型的操作来处理 BigDecimal 的标度:标度/舍入操作和小数点移动操作。标度/舍入操作(setScale 和 round)返回 BigDecimal,其值近似地(或精确地)等于操作数的值,但是其标度或精度是指定的值;即:它们会增加或减少对其值具有最小影响的存储数的精度。小数点移动操作(movePointLeft 和 movePointRight)返回从操作数创建的 BigDecimal,创建的方法是按指定方向将小数点移动一个指定距离。
    Java代码  收藏代码
    1. setScale  
    2.   
    3. public BigDecimal setScale(int newScale,  
    4.                            int roundingMode)  
    5. 返回一个 BigDecimal,其标度为指定值,其非标度值通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定,  
    6. 以维护其总值。如果该操作减少标度,则非标度值必须被除(而不是乘),并且该值可以更改;在这种情况下,将指定的  
    7. 舍入模式应用到除法中。  
    8. 注意,由于 BigDecimal 对象是不可变的,此方法的调用不会 导致初始对象被修改,  
    9. 这与使用名为 setX 变异字段 X 方法的常规约定相反。相反,setScale 返回具有适当标度的对象;  
    10. 返回的对象不一定是新分配的。  
    11.   
    12. 相对于此遗留方法,应优先使用新的 setScale(int, RoundingMode) 方法。  
    13.   
    14. 参数:  
    15. newScale - 要返回的 BigDecimal 值的标度。  
    16. roundingMode - 要应用的舍入模式。  
    17. 返回:  
    18. 一个 BigDecimal,其标度为指定值,其非标度值可以通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定。  

    RoundingMode的API

    枚举常量摘要

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

      看完这些前面那个:

    Java代码  收藏代码
    1. result.setScale(2,BigDecimal.ROUND_HALF_EVEN)  

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

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

    ————————————————————————————————————————————————————

    转自:http://blog.csdn.net/lujinan858/article/details/4371099

    1. 

    String myMoney = "100.0128"; 

      BigDecimal money= new BigDecimal(myMoney); 

      //设置精度,以及舍入规则 
      money= money.setScale(2, BigDecimal.ROUND_HALF_UP); 

      System.out.println(money); 

      //100.01 



    2. double myMoney = 100.0128; 

       myMoney  = Math.round(myMoney  * 100) / (double) 100  ; 

        BigDecimal money= new BigDecimal(myMoney); 

        System.out.println(money); //后面则有很多的小数 

       //为了保证小数位数为2位 

       BigDecimal money= new BigDecimal(Double.toString(myMoney)); 

        System.out.println(money); //小数位数则为2位 



    这个类确实好用。在网上找到的,是一个女Java程序员写的。厉害~~~~~~哈哈

    1. /* 
    2. * 创建日期 2004-10-14 
    3. * 
    4. * 如果需要精确计算,非要用String来够造BigDecimal不可 
    5. */  
    6. package com.lims.actions.testqc.comm;  
    7. /** 
    8. * @author Jstar 
    9. * 
    10. * 
    11. * 窗口 > 首选项 > Java > 代码生成 > 代码和注释 
    12. */  
    13. import java.math.BigDecimal;  
    14. /** 
    15. * 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精 
    16. * 确的浮点数运算,包括加减乘除和四舍五入。 
    17. */  
    18. public class Arith {  
    19. //默认除法运算精度  
    20. private static final int DEF_DIV_SCALE = 10;  
    21. //这个类不能实例化  
    22. private Arith() {  
    23. }  
    24. /** 
    25.   * 提供精确的加法运算。 
    26.   * @param v1 被加数 
    27.   * @param v2 加数 
    28.   * @return 两个参数的和 
    29.   */  
    30. public static double add(double v1, double v2) {  
    31.   BigDecimal b1 = new BigDecimal(Double.toString(v1));  
    32.   BigDecimal b2 = new BigDecimal(Double.toString(v2));  
    33.   
    34.   return b1.add(b2).doubleValue();  
    35. }  
    36. /** 
    37.   * 提供精确的减法运算。 
    38.   * @param v1 被减数 
    39.   * @param v2 减数 
    40.   * @return 两个参数的差 
    41.   */  
    42. public static double sub(double v1, double v2) {  
    43.   BigDecimal b1 = new BigDecimal(Double.toString(v1));  
    44.   BigDecimal b2 = new BigDecimal(Double.toString(v2));  
    45.   return b1.subtract(b2).doubleValue();  
    46. }  
    47. /** 
    48.   * 提供精确的乘法运算。 
    49.   * @param v1 被乘数 
    50.   * @param v2 乘数 
    51.   * @return 两个参数的积 
    52.   */  
    53. public static double mul(double v1, double v2) {  
    54.   BigDecimal b1 = new BigDecimal(Double.toString(v1));  
    55.   BigDecimal b2 = new BigDecimal(Double.toString(v2));  
    56.   return b1.multiply(b2).doubleValue();  
    57. }  
    58. /** 
    59.   * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 
    60.   * 小数点以后10位,以后的数字四舍五入。 
    61.   * @param v1 被除数 
    62.   * @param v2 除数 
    63.   * @return 两个参数的商 
    64.   */  
    65. public static double div(double v1, double v2) {  
    66.   return div(v1, v2, DEF_DIV_SCALE);  
    67. }  
    68. /** 
    69.   * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 
    70.   * 定精度,以后的数字四舍五入。 
    71.   * @param v1 被除数 
    72.   * @param v2 除数 
    73.   * @param scale 表示表示需要精确到小数点以后几位。 
    74.   * @return 两个参数的商 
    75.   */  
    76. public static double div(double v1, double v2, int scale) {  
    77.   if (scale < 0) {  
    78. throw new IllegalArgumentException("The scale must be a positive integer or zero");  
    79.   }  
    80.   BigDecimal b = new BigDecimal(Double.toString(v));  
    81.   BigDecimal one = new BigDecimal("1");  
    82.   return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();  
    83. }   
  • 相关阅读:
    firebird database (快速入門)
    firebird的数据类型(datatype)
    通过ASP.NET获取URL地址方法
    FIREBIRD使用经验总结
    C# Append a host header to a website in IIS by code
    Ubuntu 9.04 下载镜像地址
    Firebird如何防止空值扩散
    Tmail: 开源邮件服务器软件包
    Firebird中的NULL
    本地数据源:使用firebird数据库
  • 原文地址:https://www.cnblogs.com/wangpei/p/3287351.html
Copyright © 2011-2022 走看看