zoukankan      html  css  js  c++  java
  • 编写高质量代码:改善Java程序的151个建议(第2章:基本类型___建议21~25)

                                               不积跬步,无以至千里;

                                          不积小流,无以成江海。

                                                   ———荀子《劝学篇》

    建议21:用偶判断,不用奇判断

       判断一个数是奇数还是偶数是小学里的基本知识,能够被2整除的整数是偶数,不能被2整除的数是奇数,这规则简单明了,还有什么可考虑的?好,我们来看一个例子,代码如下: 

     1 import java.util.Scanner;
     2 
     3 public class Client21 {
     4     public static void main(String[] args) {
     5         // 接收键盘输入参数
     6         Scanner input = new Scanner(System.in);
     7         System.out.println("输入多个数字判断奇偶:");
     8         while (input.hasNextInt()) {
     9             int i = input.nextInt();
    10             String str = i + "-->" + (i % 2 == 1 ? "奇数" : "偶数");
    11             System.out.println(str);
    12 
    13         }
    14     }
    15 }

    输入多个数字,然后判断每个数字的奇偶性,不能被2整除的就是奇数,其它的都是偶数,完全是根据奇偶数的定义编写的程序,我们开看看打印的结果:

      输入多个数字判断奇偶:1  2  0  -1 -2     1-->奇数    2-->偶数    0-->偶数     -1-->偶数       -2-->偶数

    前三个还很靠谱,第四个参数-1怎么可能是偶数呢,这Java也太差劲了吧。如此简单的计算也会出错!别忙着下结论,我们先来了解一下Java中的取余(%标识符)算法,模拟代码如下:

    // 模拟取余计算,dividend被除数,divisor除数
        public static int remainder(int dividend, int divisor) {
            return dividend - dividend / divisor * divisor;
        }

    看到这段程序,大家都会心的笑了,原来Java这么处理取余计算的呀,根据上面的模拟取余可知,当输入-1的时候,运算结果为-1,当然不等于1了,所以它就被判定为偶数了,也就是我们的判断失误了。问题明白了,修正也很简单,改为判断是否是偶数即可。代码如下:     i % 2 == 0 ? "偶数" : "奇数";

    注意:对于基础知识,我们应该"知其然,并知其所以然"。

    建议22:用整数类型处理货币

     在日常生活中,最容易接触到的小数就是货币,比如,你付给售货员10元钱购买一个9.6元的零食,售货员应该找你0.4元,也就是4毛钱才对,我们来看下面的程序:

    public class Client22 {
        public static void main(String[] args) {
            System.out.println(10.00-9.60);
        }
    }

    我们的期望结果是0.4,也应该是这个数字,但是打印出来的却是:0.40000000000000036,这是为什么呢?

      这是因为在计算机中浮点数有可能(注意是有可能)是不准确的,它只能无限接近准确值,而不能完全精确。为什么会如此呢?这是由浮点数的存储规则所决定的,我们先来看看0.4这个十进制小数如何转换成二进制小数,使用"乘2取整,顺序排列"法(不懂,这就没招了,这太基础了),我们发现0.4不能使用二进制准确的表示,在二进制数世界里它是一个无限循环的小数,也就是说,"展示"  都不能 "展示",更别说在内存中存储了(浮点数的存储包括三部分:符号位、指数位、尾数,具体不再介绍),可以这样理解,在十进制的世界里没有办法唯一准确表示1/3,那么在二进制的世界里当然也无法准确表示1/5(如果二进制也有分数的话倒是可以表示),在二进制的世界里1/5是一个无限循环的小数。

      大家可能要说了,那我对结果取整不就对了吗?代码如下

    public class Client22 {
        public static void main(String[] args) {
            NumberFormat f = new DecimalFormat("#.##");
            System.out.println(f.format(10.00-9.60));
        }
    }

    打印出的结果是0.4,看似解决了。但是隐藏了一个很深的问题。我们来思考一下金融行业的计算方法,会计系统一般记录小数点后的4为小数,但是在汇总、展现、报表中、则只记录小数点后的2位小数,如果使用浮点数来计算货币,想想看,在大批量加减乘除后结果会有很大的差距(其中还涉及到四舍五入的问题)!会计系统要求的就是准确,但是因为计算机的缘故不准确了,那真是罪过,要解决此问题有两种方法:

    (1)、使用BigDecimal

        BigDecimal是专门为弥补浮点数无法精确计算的缺憾而设计的类,并且它本身也提供了加减乘除的常用数学算法。特别是与数据库Decimal类型的字段映射时,BigDecimal是最优的解决方案。

    (2)、使用整型

        把参与运算的值扩大100倍,并转为整型,然后在展现时再缩小100倍,这样处理的好处是计算简单,准确,一般在非金融行业(如零售行业)应用较多。此方法还会用于某些零售POS机,他们输入和输出的全部是整数,那运算就更简单了.

    建议23:不要让类型默默转换

       我们做一个小学生的题目,光速每秒30万公里,根据光线的旅行时间,计算月球和地球,太阳和地球之间的距离。代码如下: 

     1 public class Client23 {
     2     // 光速是30万公里/秒,常量
     3     public static final int LIGHT_SPEED = 30 * 10000 * 1000;
     4 
     5     public static void main(String[] args) {
     6         System.out.println("题目1:月球照射到地球需要一秒,计算月亮和地球的距离。");
     7         long dis1 = LIGHT_SPEED * 1;
     8         System.out.println("月球与地球的距离是:" + dis1 + " 米 ");
     9         System.out.println("-------------------------------");
    10         System.out.println("题目2:太阳光照射到地球需要8分钟,计算太阳到地球的距离.");
    11         // 可能要超出整数范围,使用long型
    12         long dis2 = LIGHT_SPEED * 60 * 8;
    13         System.out.println("太阳与地球之间的距离是:" + dis2 + " 米");
    14     }
    15 }

      估计有人鄙视了,这种小学生的乘法有神么可做的,不错,就是一个乘法运算,我们运行之后的结果如下:

        题目1:月球照射到地球需要一秒,计算月亮和地球的距离。
           月球与地球的距离是:300000000 米
            -------------------------------
           题目2:太阳光照射到地球需要8分钟,计算太阳到地球的距离.
           太阳与地球之间的距离是:-2028888064 米

      太阳和地球的距离竟然是负的,诡异。dis2不是已经考虑到int类型可能越界的问题,并使用了long型吗,怎么还会出现负值呢?

      那是因为Java是先运算然后进行类型转换的,具体的说就是因为dis2的三个运算参数都是int型,三者相乘的结果虽然也是int型,但是已经超过了int的最大值,所以其值就是负值了(为什么是负值,因为过界了就会重头开始),再转换为long型,结果还是负值。

      问题知道了,解决起来也很简单,只要加个小小的L即可,代码如下:

      long dis2 = LIGHT_SPEED * 60L * 8;

      60L是一个长整型,乘出来的结果也是一个长整型的(此乃Java的基本转换规则,向数据范围大的方向转换,也就是加宽类型),在还没有超过int类型的范围时就已经转换为long型了,彻底解决了越界问题。在实际开发中,更通用的做法是主动声明类型转化(注意,不是强制类型转换)代码如下:

      long dis2 = 1L * LIGHT_SPEED * 60L * 8

      既然期望的结果是long型,那就让第一个参与的参数也是Long(1L)吧,也就说明"嗨"我已经是长整型了,你们都跟着我一块转为长整型吧。

    注意:基本类型转换时,使用主动声明方式减少不必要的Bug.

    建议24:边界还是边界

       某商家生产的电子产品非常畅销,需要提前30天预订才能抢到手,同时还规定了一个会员可拥有的最多产品数量,目的是为了防止囤积压货肆意加价。会员的预订过程是这样的:先登录官方网站,选择产品型号,然后设置需要预订的数量,提交,符合规则即提示下单成功,不符合规则提示下单失败,后台的处理模拟如下:

     1 import java.util.Scanner;
     2 
     3 public class Client24 {
     4     // 一个会员拥有产品的最多数量
     5     public final static int LIMIT = 2000;
     6 
     7     public static void main(String[] args) {
     8         // 会员当前用有的产品数量
     9         int cur = 1000;
    10         Scanner input = new Scanner(System.in);
    11         System.out.println("请输入需要预定的数量:");
    12         while (input.hasNextInt()) {
    13             int order = input.nextInt();
    14             if (order > 0 && order + cur <= LIMIT) {
    15                 System.out.println("你已经成功预定:" + order + " 个产品");
    16             } else {
    17                 System.out.println("超过限额,预定失败!");
    18             }
    19         }
    20 
    21     }
    22 }

      这是一个简单的订单处理程序,其中cur代表的是会员当前拥有的产品数量,LIMIT是一个会员最多拥有的产品数量(现实中,这两个参数当然是从数据库中获得的,不过这里是一个模拟程序),如果当前预订数量与拥有数量之和超过了最大数量,则预订失败,否则下单成功。业务逻辑很简单,同时在web界面上对订单数量做了严格的校验,比如不能是负值、不能超过最大数量等,但是人算不如天算,运行不到两小时数据库中就出现了异常数据:某会员拥有的产品数量与预定数量之和远远大于限额。怎么会这样呢?程序逻辑上不可能有问题呀,这如何产生的呢?我们来模拟一下,第一次输入:

      请输入需要预定的数量:800    你已经成功预定800个产品

      这完全满足条件,没有任何问题,继续输入:

      请输入需要预定的数量:2147483647   你已经成功预定2147483647个产品

      看到没有,这个数字已经远远超过了2000的限额,但是竟然预定成功了,真实神奇!
      看着2147483647这个数字很眼熟?那就对了,这个数字就是int类型的最大值,没错,有人输入了一个最大值,使校验条件失败了,Why?我们来看程序,order的值是2147483647那再加上1000就超出int的范围了,其结果是-2147482649,那当然是小于正数2000了!一句归其原因:数字越界使校验条件失效。

      在单元测试中,有一项测试叫做边界测试(也叫临界测试),如果一个方法接收的是int类型的参数,那么以下三个值是必须测试的:0、正最大、负最小,其中正最大、负最小是边界值,如果这三个值都没有问题,方法才是比较安全可靠的。我们的例子就是因为缺少边界测试,致使生产系统产生了严重的偏差。

      也许你要疑惑了,Web界面已经做了严格的校验,为什么还能输入2147483647  这么大的数字呢?是否说明Web校验不严格?错了,不是这样的,Web校验都是在页面上通过JavaScript实现的,只能限制普通用户(这里的普通用户是指不懂html,不懂HTTP,不懂Java的简单使用者),而对于高手,这些校验基本上就是摆设,HTTP是明文传输的,将其拦截几次,分析一下数据结构,然后写一个模拟器,一切前端校验就成了浮云!想往后台提交个什么数据还不是信手拈来!

    建议25:不要让四舍五入亏了一方

       本建议还是来重温一个小学数学问题:四舍五入。四舍五入是一种近似精确的计算方法,在Java5之前,我们一般是通过Math.round来获得指定精度的整数或小数的,这种方法使用非常广泛,代码如下:

    public class Client25 {
        public static void main(String[] args) {
            System.out.println("10.5近似值: "+Math.round(10.5));
            System.out.println("-10.5近似值: "+Math.round(-10.5));
        }
    }

    输出结果为:10.5近似值: 11       -10.5近似值: -10
      这是四舍五入的经典案例,也是初级面试官很乐意选择的考题,绝对值相同的两个数字,近似值为什么就不同了呢?这是由Math.round采用的舍入规则决定的(采用的是正无穷方向舍入规则),我们知道四舍五入是有误差的:其误差值是舍入的一半。我们以舍入运用最频繁的银行利息计算为例来阐述此问题。

      我们知道银行的盈利渠道主要是利息差,从储户手里收拢资金,然后房贷出去,期间的利息差额便是所获得利润,对一个银行来说,对付给储户的利息计算非常频繁,人民银行规定每个季度末月的20日为银行结息日,一年有4次的结息日。

      场景介绍完毕,我们回头来看看四舍五入,小于5的数字被舍去,大于5的数字进位后舍去,由于单位上的数字都是自然计算出来的,按照利率计算可知,被舍去的数字都分布在0~9之间,下面以10笔存款利息计算作为模型,以银行家的身份来思考这个算法:

      四舍:舍弃的数值是:0.000、0.001、0.002、0.003、0.004因为是舍弃的,对于银行家来说就不需要付款给储户了,那每舍一个数字就会赚取相应的金额:0.000、0.001、0.002、0.003、0.004.

      五入:进位的数值是:0.005、0.006、0.007、0.008、0.009,因为是进位,对银行家来说,每进一位就会多付款给储户,也就是亏损了,那亏损部分就是其对应的10进制补数:0.005、.0004、0.003、0.002、0.001.

      因为舍弃和进位的数字是均匀分布在0~9之间,对于银行家来说,没10笔存款的利息因采用四舍五入而获得的盈利是:

      0.000 + 0.001 + 0.002 + 0.003 + 0.004 - 0.005 - 0.004 - 0.003 - 0.002 - 0.001 = - 0.005;

      也就是说,每10笔利息计算中就损失0.005元,即每笔利息计算就损失0.0005元,这对一家有5千万储户的银行家来说(对国内银行来说,5千万是个小数字),每年仅仅因为四舍五入的误差而损失的金额是:

      银行账户数量(5千万)*4(一年计算四次利息)*0.0005(每笔利息损失的金额)

      5000*10000*0.0005*4=100000.0;即,每年因为一个算法误差就损失了10万元,事实上以上的假设条件都是非常保守的,实际情况可能损失的更多。那各位可能要说了,银行还要放贷呀,放出去这笔计算误差不就抵消了吗?不会抵消,银行的贷款数量是非常有限的其数量级根本无法和存款相比。

      这个算法误差是由美国银行家发现的(那可是私人银行,钱是自己的,白白损失了可不行),并且对此提出了一个修正算法,叫做银行家舍入(Banker's Round)的近似算法,其规则如下:

    1. 舍去位的数值小于5时,直接舍去;
    2. 舍去位的数值大于等于6时,进位后舍去;
    3. 当舍去位的数值等于5时,分两种情况:5后面还有其它数字(非0),则进位后舍去;若5后面是0(即5是最后一个数字),则根据5前一位数的奇偶性来判断是否需要进位,奇数进位,偶数舍去。

      以上规则汇总成一句话:四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。我们举例说明,取2位精度;

      round(10.5551)  =  10.56   round(10.555)  =  10.56   round(10.545)  =  10.54 

      要在Java5以上的版本中使用银行家的舍入法则非常简单,直接使用RoundingMode类提供的Round模式即可,示例代码如下:  

     1 import java.math.BigDecimal;
     2 import java.math.RoundingMode;
     3 
     4 public class Client25 {
     5     public static void main(String[] args) {
     6         // 存款
     7         BigDecimal d = new BigDecimal(888888);
     8         // 月利率,乘3计算季利率
     9         BigDecimal r = new BigDecimal(0.001875*3);
    10         //计算利息
    11         BigDecimal i =d.multiply(r).setScale(2,RoundingMode.HALF_EVEN);
    12         System.out.println("季利息是:"+i);
    13         
    14     }
    15 }

    在上面的例子中,我们使用了BigDecimal类,并且采用了setScale方法设置了精度,同时传递了一个RoundingMode.HALF_EVEN参数表示使用银行家法则进行近似计算,BigDecimal和RoundingMode是一个绝配,想要采用什么方式使用RoundingMode设置即可。目前Java支持以下七种舍入方式:

    1. ROUND_UP:原理零方向舍入。向远离0的方向舍入,也就是说,向绝对值最大的方向舍入,只要舍弃位非0即进位。
    2. ROUND_DOWN:趋向0方向舍入。向0方向靠拢,也就是说,向绝对值最小的方向输入,注意:所有的位都舍弃,不存在进位情况。
    3. ROUND_CEILING:向正无穷方向舍入。向正最大方向靠拢,如果是正数,舍入行为类似于ROUND_UP;如果为负数,则舍入行为类似于ROUND_DOWN.注意:Math.round方法使用的即为此模式。
    4. ROUND_FLOOR:向负无穷方向舍入。向负无穷方向靠拢,如果是正数,则舍入行为类似ROUND_DOWN,如果是负数,舍入行为类似以ROUND_UP。
    5. HALF_UP:最近数字舍入(5舍),这就是我们经典的四舍五入。
    6. HALF_DOWN:最近数字舍入(5舍)。在四舍五入中,5是进位的,在HALF_DOWN中却是舍弃不进位。
    7. HALF_EVEN:银行家算法

      在普通的项目中舍入模式不会有太多影响,可以直接使用Math.round方法,但在大量与货币数字交互的项目中,一定要选择好近似的计算模式,尽量减少因算法不同而造成的损失。

    注意:根据不同的场景,慎重选择不同的舍入模式,以提高项目的精准度,减少算法损失。

    附录:此处说的这些常量全部来自java的RoundingMode类,故而贴出此类的源码供大家参考。

      1 package java.math;
      2 /**
      3  * Specifies a <i>rounding behavior</i> for numerical operations
      4  * capable of discarding precision. Each rounding mode indicates how
      5  * the least significant returned digit of a rounded result is to be
      6  * calculated.  If fewer digits are returned than the digits needed to
      7  * represent the exact numerical result, the discarded digits will be
      8  * referred to as the <i>discarded fraction</i> regardless the digits'
      9  * contribution to the value of the number.  In other words,
     10  * considered as a numerical value, the discarded fraction could have
     11  * an absolute value greater than one.
     12  *
     13  * <p>Each rounding mode description includes a table listing how
     14  * different two-digit decimal values would round to a one digit
     15  * decimal value under the rounding mode in question.  The result
     16  * column in the tables could be gotten by creating a
     17  * {@code BigDecimal} number with the specified value, forming a
     18  * {@link MathContext} object with the proper settings
     19  * ({@code precision} set to {@code 1}, and the
     20  * {@code roundingMode} set to the rounding mode in question), and
     21  * calling {@link BigDecimal#round round} on this number with the
     22  * proper {@code MathContext}.  A summary table showing the results
     23  * of these rounding operations for all rounding modes appears below.
     24  *
     25  *<p>
     26  *<table border>
     27  * <caption><b>Summary of Rounding Operations Under Different Rounding Modes</b></caption>
     28  * <tr><th></th><th colspan=8>Result of rounding input to one digit with the given
     29  *                           rounding mode</th>
     30  * <tr valign=top>
     31  * <th>Input Number</th>         <th>{@code UP}</th>
     32  *                                           <th>{@code DOWN}</th>
     33  *                                                        <th>{@code CEILING}</th>
     34  *                                                                       <th>{@code FLOOR}</th>
     35  *                                                                                    <th>{@code HALF_UP}</th>
     36  *                                                                                                   <th>{@code HALF_DOWN}</th>
     37  *                                                                                                                    <th>{@code HALF_EVEN}</th>
     38  *                                                                                                                                     <th>{@code UNNECESSARY}</th>
     39  *
     40  * <tr align=right><td>5.5</td>  <td>6</td>  <td>5</td>    <td>6</td>    <td>5</td>  <td>6</td>      <td>5</td>       <td>6</td>       <td>throw {@code ArithmeticException}</td>
     41  * <tr align=right><td>2.5</td>  <td>3</td>  <td>2</td>    <td>3</td>    <td>2</td>  <td>3</td>      <td>2</td>       <td>2</td>       <td>throw {@code ArithmeticException}</td>
     42  * <tr align=right><td>1.6</td>  <td>2</td>  <td>1</td>    <td>2</td>    <td>1</td>  <td>2</td>      <td>2</td>       <td>2</td>       <td>throw {@code ArithmeticException}</td>
     43  * <tr align=right><td>1.1</td>  <td>2</td>  <td>1</td>    <td>2</td>    <td>1</td>  <td>1</td>      <td>1</td>       <td>1</td>       <td>throw {@code ArithmeticException}</td>
     44  * <tr align=right><td>1.0</td>  <td>1</td>  <td>1</td>    <td>1</td>    <td>1</td>  <td>1</td>      <td>1</td>       <td>1</td>       <td>1</td>
     45  * <tr align=right><td>-1.0</td> <td>-1</td> <td>-1</td>   <td>-1</td>   <td>-1</td> <td>-1</td>     <td>-1</td>      <td>-1</td>      <td>-1</td>
     46  * <tr align=right><td>-1.1</td> <td>-2</td> <td>-1</td>   <td>-1</td>   <td>-2</td> <td>-1</td>     <td>-1</td>      <td>-1</td>      <td>throw {@code ArithmeticException}</td>
     47  * <tr align=right><td>-1.6</td> <td>-2</td> <td>-1</td>   <td>-1</td>   <td>-2</td> <td>-2</td>     <td>-2</td>      <td>-2</td>      <td>throw {@code ArithmeticException}</td>
     48  * <tr align=right><td>-2.5</td> <td>-3</td> <td>-2</td>   <td>-2</td>   <td>-3</td> <td>-3</td>     <td>-2</td>      <td>-2</td>      <td>throw {@code ArithmeticException}</td>
     49  * <tr align=right><td>-5.5</td> <td>-6</td> <td>-5</td>   <td>-5</td>   <td>-6</td> <td>-6</td>     <td>-5</td>      <td>-6</td>      <td>throw {@code ArithmeticException}</td>
     50  *</table>
     51  *
     52  *
     53  * <p>This {@code enum} is intended to replace the integer-based
     54  * enumeration of rounding mode constants in {@link BigDecimal}
     55  * ({@link BigDecimal#ROUND_UP}, {@link BigDecimal#ROUND_DOWN},
     56  * etc. ).
     57  *
     58  * @see     BigDecimal
     59  * @see     MathContext
     60  * @author  Josh Bloch
     61  * @author  Mike Cowlishaw
     62  * @author  Joseph D. Darcy
     63  * @since 1.5
     64  */
     65 public enum RoundingMode {
     66 
     67         /**
     68          * Rounding mode to round away from zero.  Always increments the
     69          * digit prior to a non-zero discarded fraction.  Note that this
     70          * rounding mode never decreases the magnitude of the calculated
     71          * value.
     72          *
     73          *<p>Example:
     74          *<table border>
     75          *<tr valign=top><th>Input Number</th>
     76          *    <th>Input rounded to one digit<br> with {@code UP} rounding
     77          *<tr align=right><td>5.5</td>  <td>6</td>
     78          *<tr align=right><td>2.5</td>  <td>3</td>
     79          *<tr align=right><td>1.6</td>  <td>2</td>
     80          *<tr align=right><td>1.1</td>  <td>2</td>
     81          *<tr align=right><td>1.0</td>  <td>1</td>
     82          *<tr align=right><td>-1.0</td> <td>-1</td>
     83          *<tr align=right><td>-1.1</td> <td>-2</td>
     84          *<tr align=right><td>-1.6</td> <td>-2</td>
     85          *<tr align=right><td>-2.5</td> <td>-3</td>
     86          *<tr align=right><td>-5.5</td> <td>-6</td>
     87          *</table>
     88          */
     89     UP(BigDecimal.ROUND_UP),
     90 
     91         /**
     92          * Rounding mode to round towards zero.  Never increments the digit
     93          * prior to a discarded fraction (i.e., truncates).  Note that this
     94          * rounding mode never increases the magnitude of the calculated value.
     95          *
     96          *<p>Example:
     97          *<table border>
     98          *<tr valign=top><th>Input Number</th>
     99          *    <th>Input rounded to one digit<br> with {@code DOWN} rounding
    100          *<tr align=right><td>5.5</td>  <td>5</td>
    101          *<tr align=right><td>2.5</td>  <td>2</td>
    102          *<tr align=right><td>1.6</td>  <td>1</td>
    103          *<tr align=right><td>1.1</td>  <td>1</td>
    104          *<tr align=right><td>1.0</td>  <td>1</td>
    105          *<tr align=right><td>-1.0</td> <td>-1</td>
    106          *<tr align=right><td>-1.1</td> <td>-1</td>
    107          *<tr align=right><td>-1.6</td> <td>-1</td>
    108          *<tr align=right><td>-2.5</td> <td>-2</td>
    109          *<tr align=right><td>-5.5</td> <td>-5</td>
    110          *</table>
    111          */
    112     DOWN(BigDecimal.ROUND_DOWN),
    113 
    114         /**
    115          * Rounding mode to round towards positive infinity.  If the
    116          * result is positive, behaves as for {@code RoundingMode.UP};
    117          * if negative, behaves as for {@code RoundingMode.DOWN}.  Note
    118          * that this rounding mode never decreases the calculated value.
    119          *
    120          *<p>Example:
    121          *<table border>
    122          *<tr valign=top><th>Input Number</th>
    123          *    <th>Input rounded to one digit<br> with {@code CEILING} rounding
    124          *<tr align=right><td>5.5</td>  <td>6</td>
    125          *<tr align=right><td>2.5</td>  <td>3</td>
    126          *<tr align=right><td>1.6</td>  <td>2</td>
    127          *<tr align=right><td>1.1</td>  <td>2</td>
    128          *<tr align=right><td>1.0</td>  <td>1</td>
    129          *<tr align=right><td>-1.0</td> <td>-1</td>
    130          *<tr align=right><td>-1.1</td> <td>-1</td>
    131          *<tr align=right><td>-1.6</td> <td>-1</td>
    132          *<tr align=right><td>-2.5</td> <td>-2</td>
    133          *<tr align=right><td>-5.5</td> <td>-5</td>
    134          *</table>
    135          */
    136     CEILING(BigDecimal.ROUND_CEILING),
    137 
    138         /**
    139          * Rounding mode to round towards negative infinity.  If the
    140          * result is positive, behave as for {@code RoundingMode.DOWN};
    141          * if negative, behave as for {@code RoundingMode.UP}.  Note that
    142          * this rounding mode never increases the calculated value.
    143          *
    144          *<p>Example:
    145          *<table border>
    146          *<tr valign=top><th>Input Number</th>
    147          *    <th>Input rounded to one digit<br> with {@code FLOOR} rounding
    148          *<tr align=right><td>5.5</td>  <td>5</td>
    149          *<tr align=right><td>2.5</td>  <td>2</td>
    150          *<tr align=right><td>1.6</td>  <td>1</td>
    151          *<tr align=right><td>1.1</td>  <td>1</td>
    152          *<tr align=right><td>1.0</td>  <td>1</td>
    153          *<tr align=right><td>-1.0</td> <td>-1</td>
    154          *<tr align=right><td>-1.1</td> <td>-2</td>
    155          *<tr align=right><td>-1.6</td> <td>-2</td>
    156          *<tr align=right><td>-2.5</td> <td>-3</td>
    157          *<tr align=right><td>-5.5</td> <td>-6</td>
    158          *</table>
    159          */
    160     FLOOR(BigDecimal.ROUND_FLOOR),
    161 
    162         /**
    163          * Rounding mode to round towards {@literal "nearest neighbor"}
    164          * unless both neighbors are equidistant, in which case round up.
    165          * Behaves as for {@code RoundingMode.UP} if the discarded
    166          * fraction is &ge; 0.5; otherwise, behaves as for
    167          * {@code RoundingMode.DOWN}.  Note that this is the rounding
    168          * mode commonly taught at school.
    169          *
    170          *<p>Example:
    171          *<table border>
    172          *<tr valign=top><th>Input Number</th>
    173          *    <th>Input rounded to one digit<br> with {@code HALF_UP} rounding
    174          *<tr align=right><td>5.5</td>  <td>6</td>
    175          *<tr align=right><td>2.5</td>  <td>3</td>
    176          *<tr align=right><td>1.6</td>  <td>2</td>
    177          *<tr align=right><td>1.1</td>  <td>1</td>
    178          *<tr align=right><td>1.0</td>  <td>1</td>
    179          *<tr align=right><td>-1.0</td> <td>-1</td>
    180          *<tr align=right><td>-1.1</td> <td>-1</td>
    181          *<tr align=right><td>-1.6</td> <td>-2</td>
    182          *<tr align=right><td>-2.5</td> <td>-3</td>
    183          *<tr align=right><td>-5.5</td> <td>-6</td>
    184          *</table>
    185          */
    186     HALF_UP(BigDecimal.ROUND_HALF_UP),
    187 
    188         /**
    189          * Rounding mode to round towards {@literal "nearest neighbor"}
    190          * unless both neighbors are equidistant, in which case round
    191          * down.  Behaves as for {@code RoundingMode.UP} if the discarded
    192          * fraction is &gt; 0.5; otherwise, behaves as for
    193          * {@code RoundingMode.DOWN}.
    194          *
    195          *<p>Example:
    196          *<table border>
    197          *<tr valign=top><th>Input Number</th>
    198          *    <th>Input rounded to one digit<br> with {@code HALF_DOWN} rounding
    199          *<tr align=right><td>5.5</td>  <td>5</td>
    200          *<tr align=right><td>2.5</td>  <td>2</td>
    201          *<tr align=right><td>1.6</td>  <td>2</td>
    202          *<tr align=right><td>1.1</td>  <td>1</td>
    203          *<tr align=right><td>1.0</td>  <td>1</td>
    204          *<tr align=right><td>-1.0</td> <td>-1</td>
    205          *<tr align=right><td>-1.1</td> <td>-1</td>
    206          *<tr align=right><td>-1.6</td> <td>-2</td>
    207          *<tr align=right><td>-2.5</td> <td>-2</td>
    208          *<tr align=right><td>-5.5</td> <td>-5</td>
    209          *</table>
    210          */
    211     HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),
    212 
    213         /**
    214          * Rounding mode to round towards the {@literal "nearest neighbor"}
    215          * unless both neighbors are equidistant, in which case, round
    216          * towards the even neighbor.  Behaves as for
    217          * {@code RoundingMode.HALF_UP} if the digit to the left of the
    218          * discarded fraction is odd; behaves as for
    219          * {@code RoundingMode.HALF_DOWN} if it's even.  Note that this
    220          * is the rounding mode that statistically minimizes cumulative
    221          * error when applied repeatedly over a sequence of calculations.
    222          * It is sometimes known as {@literal "Banker's rounding,"} and is
    223          * chiefly used in the USA.  This rounding mode is analogous to
    224          * the rounding policy used for {@code float} and {@code double}
    225          * arithmetic in Java.
    226          *
    227          *<p>Example:
    228          *<table border>
    229          *<tr valign=top><th>Input Number</th>
    230          *    <th>Input rounded to one digit<br> with {@code HALF_EVEN} rounding
    231          *<tr align=right><td>5.5</td>  <td>6</td>
    232          *<tr align=right><td>2.5</td>  <td>2</td>
    233          *<tr align=right><td>1.6</td>  <td>2</td>
    234          *<tr align=right><td>1.1</td>  <td>1</td>
    235          *<tr align=right><td>1.0</td>  <td>1</td>
    236          *<tr align=right><td>-1.0</td> <td>-1</td>
    237          *<tr align=right><td>-1.1</td> <td>-1</td>
    238          *<tr align=right><td>-1.6</td> <td>-2</td>
    239          *<tr align=right><td>-2.5</td> <td>-2</td>
    240          *<tr align=right><td>-5.5</td> <td>-6</td>
    241          *</table>
    242          */
    243     HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
    244 
    245         /**
    246          * Rounding mode to assert that the requested operation has an exact
    247          * result, hence no rounding is necessary.  If this rounding mode is
    248          * specified on an operation that yields an inexact result, an
    249          * {@code ArithmeticException} is thrown.
    250          *<p>Example:
    251          *<table border>
    252          *<tr valign=top><th>Input Number</th>
    253          *    <th>Input rounded to one digit<br> with {@code UNNECESSARY} rounding
    254          *<tr align=right><td>5.5</td>  <td>throw {@code ArithmeticException}</td>
    255          *<tr align=right><td>2.5</td>  <td>throw {@code ArithmeticException}</td>
    256          *<tr align=right><td>1.6</td>  <td>throw {@code ArithmeticException}</td>
    257          *<tr align=right><td>1.1</td>  <td>throw {@code ArithmeticException}</td>
    258          *<tr align=right><td>1.0</td>  <td>1</td>
    259          *<tr align=right><td>-1.0</td> <td>-1</td>
    260          *<tr align=right><td>-1.1</td> <td>throw {@code ArithmeticException}</td>
    261          *<tr align=right><td>-1.6</td> <td>throw {@code ArithmeticException}</td>
    262          *<tr align=right><td>-2.5</td> <td>throw {@code ArithmeticException}</td>
    263          *<tr align=right><td>-5.5</td> <td>throw {@code ArithmeticException}</td>
    264          *</table>
    265          */
    266     UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);
    267 
    268     // Corresponding BigDecimal rounding constant
    269     final int oldMode;
    270 
    271     /**
    272      * Constructor
    273      *
    274      * @param oldMode The {@code BigDecimal} constant corresponding to
    275      *        this mode
    276      */
    277     private RoundingMode(int oldMode) {
    278         this.oldMode = oldMode;
    279     }
    280 
    281     /**
    282      * Returns the {@code RoundingMode} object corresponding to a
    283      * legacy integer rounding mode constant in {@link BigDecimal}.
    284      *
    285      * @param  rm legacy integer rounding mode to convert
    286      * @return {@code RoundingMode} corresponding to the given integer.
    287      * @throws IllegalArgumentException integer is out of range
    288      */
    289     public static RoundingMode valueOf(int rm) {
    290         switch(rm) {
    291 
    292         case BigDecimal.ROUND_UP:
    293             return UP;
    294 
    295         case BigDecimal.ROUND_DOWN:
    296             return DOWN;
    297 
    298         case BigDecimal.ROUND_CEILING:
    299             return CEILING;
    300 
    301         case BigDecimal.ROUND_FLOOR:
    302             return FLOOR;
    303 
    304         case BigDecimal.ROUND_HALF_UP:
    305             return HALF_UP;
    306 
    307         case BigDecimal.ROUND_HALF_DOWN:
    308             return HALF_DOWN;
    309 
    310         case BigDecimal.ROUND_HALF_EVEN:
    311             return HALF_EVEN;
    312 
    313         case BigDecimal.ROUND_UNNECESSARY:
    314             return UNNECESSARY;
    315 
    316         default:
    317             throw new IllegalArgumentException("argument out of range");
    318         }
    319     }
    320 }
  • 相关阅读:
    凤凰网面试经历——钢管舞也算精英文化吗
    立此为证:豆瓣要做电影数字发行了(2010818)
    Officially GoldenGate was purchased by oracle in October 1, 2009
    11gR2新特性:Heavy swapping observed on system in last 5 mins.
    Oracle BMW Racing sailing vessel帆船图
    Know more about CBO Index Cost
    Samsung Epic 4G 图文介绍
    Oracle Exalogic X22 HalfRack DiagramExaloic半配图
    Java 编程下线程的生命周期
    Android 编程组件Fragments 的生命周期与 Activity 的生命周期之间的关系
  • 原文地址:https://www.cnblogs.com/selene/p/5850216.html
Copyright © 2011-2022 走看看