zoukankan      html  css  js  c++  java
  • BigDecimal

    一、 计算机的小数计算一定范围内精确,超过范围只能取近似值:

        计算机存储的浮点数受存储bit位数影响,只能保证一定范围内精准,超过bit范围的只能取近似值。
        java中各类型的精度范围参见:http://blog.csdn.net/longshenlmj/article/details/47616481
    
    编程时注意:
    doulbe类型的数,不能用等号判定是否相等(或者是一定范围内可以)。因为两次同样的计算(除法)结果可能出现小数部分不同。甚至极端的时候,初始化两个小数时,都可能不相等(用数值和字符串分别初始化bigdecimal的小数就会不等)
    

    java小数处理方法的经验总结:

    (1)小数计算对精度无要求时,使用float节省时间。
    
    (2)如果有精度要求,用BigDecimal类处理(初始化必须使用字符串,因为用数值初始化会得到近似值,不准确),然后设置保留位数和 舍入法(half_up四舍五入,half_even银行家,half_down向下取整)
    
    (3)精度要求低时可转化为整数处理(集体统一扩大数量级):
        乘以10的级数转化为整数处理,小数点右移几位,但整数值不要超过对应类型的取值范围。比如保留4位小数,可统一乘以10000,然后只保留整数计算结果,保留近位的话就多乘一位。
        这种方式在RTB项目MDSP的算法核心模块中使用,几十万的投放量,用int或long就可以处理,更大范围的整数处理BigInteger。
    

    这样的好处是:

    a,计算快,除了除法,其他运算上整数计算(加减乘)节省时间;
    b,除法中,小数部分可直接省略,或向上取整(小数大于0时则加1)也可以让小数点多移动一位来保留进位。
    

    二、java专门的小数运算类:BigDecimal类型(比double和float小数运算更精准的小数计算)

        float和double只能用来做科学计算或者是工程计算,在广域数值范围上提供较为精确的快速近似计算;而在商业计算要求结果精确(比如,有的编程语言中提供了专门的货币类型来处理),所以Java使用java.math.BigDecimal专门处理小数精度
    
    构造器描述:
        BigDecimal(int)       创建一个具有参数所指定整数值的对象。 
        BigDecimal(double)    创建一个具有参数所指定双精度值的对象。 
        BigDecimal(long)      创建一个具有参数所指定长整数值的对象。 
        BigDecimal(String)    创建一个具有参数所指定以字符串表示的数值的对象。
    

    使用原则:初始化小数必须用String来够造,BigDecimal(String),因为用double的小数是近似值,不是精确值。

    BigDecimal成员方法
        add(BigDecimal)        对象自身与参数相加,然后返回这个对象。 
        subtract(BigDecimal)   对象自身与参数相减,然后返回这个对象。 
        multiply(BigDecimal)   对象自身与参数相乘,然后返回这个对象。 
        divide(BigDecimal)     对象自身与参数相除,然后返回这个对象。 
        toString()             BigDecimal对象的数值转换成对应的字符串。 
        doubleValue()          BigDecimal对返回double值。 
        floatValue()           BigDecimal对返回float。 
        longValue()            BigDecimal对返回long值。 
        intValue()             BigDecimal对返回int值。
    

    三、java小数保留精度的舍入方式

    1,java 常用的四舍五入法实现:

    Math类中的round方法不能设置保留几位小数,但可以乘100达到保留2位的目的:
            Math.round(value*100)/100.0;
    
    或者,直接用java.text.DecimalFormat指定保留几位小数,用哪几种舍入法:
            DecimalFormat decFormat = new DecimalFormat("#.00");
            decFormat.setRoundingMode(RoundingMode.HALF_UP);
    

    2,java的8种舍入方式:

    1、 ROUND_UP:向上取整(丢掉小数,整数加1) 远离零方向舍入。向绝对值最大的方向舍入,只要舍弃位非0即进位。
    
    2、ROUND_DOWN:向下取整(丢掉小数)。趋向零方向舍入。向绝对值最小的方向输入,所有的位都要舍弃,不存在进位情况。
    
    3、ROUND_CEILING:向正无穷方向走,始终不会减少计算值。如果 BigDecimal 为正,则舍入行为与 ROUND_UP 相同;如果为负,则舍入行为与 ROUND_DOWN 相同。Math.round()方法就是使用的此模式。
    
    4、ROUND_FLOOR:向负无穷方向舍入。向负无穷方向靠拢。若是正数,舍入行为类似于ROUND_DOWN;若为负数,舍入行为类似于ROUND_UP。
    
    5、 HALF_UP:四舍五入,最近数字舍入(5进)。
    
    6、 HALF_DOWN:四舍六入,最近数字舍入(5舍)。
    
    7、 HAIL_EVEN:银行家舍入法。四舍六入五偶舍。即舍弃位4舍6入,当为5时看前一位,奇进偶舍。向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
         也就是说,如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同; 如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。
         注意,在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。
    
    8、ROUND_UNNECESSARY 断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。
    

    四、BigDecimal的java代码实例






  • 相关阅读:
    [LC] 131. Palindrome Partitioning
    [LC] 216. Combination Sum III
    [LC] 90. Subsets II
    [Algo] 73. Combinations Of Coins
    [Algo] 66. All Valid Permutations Of Parentheses I
    Hive 和 HBase区别
    form表单 多种提交方式 [转]
    HDFS 好的文章链接
    js 获取字符串的 像素 宽度 ----字符串格式化输出
    python 本地变量和全局变量 locals() globals() global nonlocal 闭包 以及和 scala 闭包的区别
  • 原文地址:https://www.cnblogs.com/xues/p/11810322.html
Copyright © 2011-2022 走看看