java BigDecimal.ROUND_UP和BigDecimal.ROUND_DOWN的用处

By SuperTaoer | 七月 10, 2010
Under: 工作分享, 程序 技术 周边
Views:

今天在工作中遇到了这样的一个需求,

一个小数,例如1.7777777,或者1.3333333,不管后面的位数是多少,只保留到小数点后第二位,但是不是四舍五入,1.7777777处理后就是1.77,1.3333333处理后就是1.33

这个就要用到BigDecimal#setScale的方法了。

具体看如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.math.BigDecimal;
import java.math.RoundingMode;
 
public class ScaleTest {
 
	public static void main(String[] args) {
 
		double a = 1.66728D;
		double b = 1.33333D;
		double c = 1.00000D;
 
		BigDecimal aa = new BigDecimal(a);
		BigDecimal bb = new BigDecimal(b);
		BigDecimal cc = new BigDecimal(c);
		System.out.println(aa.setScale(2, BigDecimal.ROUND_UP));
		System.out.println(aa.setScale(2, BigDecimal.ROUND_DOWN));
		System.out.println(bb.setScale(2, BigDecimal.ROUND_UP));
		System.out.println(bb.setScale(2, BigDecimal.ROUND_DOWN));
		System.out.println(cc.setScale(2, BigDecimal.ROUND_UP));
		System.out.println(cc.setScale(2, BigDecimal.ROUND_DOWN));
		System.out.println("-------------------------------------");
		System.out.println(aa.setScale(2, RoundingMode.UP));
		System.out.println(aa.setScale(2, RoundingMode.DOWN));
		System.out.println(bb.setScale(2, RoundingMode.UP));
		System.out.println(bb.setScale(2, RoundingMode.DOWN));
		System.out.println(cc.setScale(2, RoundingMode.UP));
		System.out.println(cc.setScale(2, RoundingMode.DOWN));
	}
}

输出结果如下:
1.67
1.66
1.34
1.33
1.00
1.00
————————————-
1.67
1.66
1.34
1.33
1.00
1.00

上面仅仅是根据我的需要举了BigDecimal.ROUND_UP和BigDecimal.ROUND_DOWN的例子,下面就用个表格来分析下。

ROUND_UP ROUND_DOWN
1.66728D 1.67 1.66
1.33333D 1.34 1.33
1.00000D 1.00 1.00

也就是说,ROUND_DOWN,是一个舍位取值的概念,我保留了两位小数,我不管你后面的小数值如何,也不会四舍五入,就硬生生的给阶段,相当于什么呢,就是我从小数点后面开始取两位,两位后面的都不要了,相当于一个截取字符串的操作。

而ROUND_UP那,很宽容,很大方,我不管你第三位的小数是多少,我都给你加一最小单位(比如保留两位小数,最小单位是0.01,保留三位小数,最小单位就是0.001),当然了,你保留到最后一位的数字如果是0的话,那么就不加了。

而这两个作用在咱们实际当中什么情况下不能使用四舍五入,需要用这两个呢?

用个应用题举例子吧,

一个篮子可以装10个苹果,现在有82个苹果,需要几个篮子来装?
9个,对,这是咱们的什么结果,不正是ROUND_UP的么(只不过这道题是取小数点后0位,也就是取整的区别而已),也就很好解释为什么最小单位是0不需要再加一个最小单位了,如果我只有80个苹果,8个篮子正好装下,就不需要第九个了。

那么什么时候儿需要使用ROUND_DOWN呢,再来看下面一个例子,
每个加油站相距8公里,一公里需要耗一个油,我现在车里还有90个油,请问,我最晚在第几个加油站必须得加油了?
11个,第十一个,就是在车使用88个油到达第11个加油站后需要加油,因为我还剩2个由已经撑不到第12个加油站了。这种情况,ROUND_DOWN就派上用场了。

其实,BigDecimal不光有ROUND_UP,ROUND_DOWN,还有其他的很多值,比如:ROUND_CEILING、ROUND_HALF_DOWN等等,具体的效果可以自己实验下。

这里给出篇文章地址供参考:
http://stephen830.javaeye.com/blog/260776 JAVA对double或者float的浮点数精度计算控制方法

原文如下:
JAVA对double或者float的浮点数精度计算控制方法
文章分类:Java编程关键字: java double或者float的浮点数精度
★★★ 本篇为原创,需要引用转载的朋友请注明:《 http://stephen830.javaeye.com/blog/260776 》 谢谢支持!★★★本篇介绍了在JAVA中如何对double或者float的浮点数进行精度计算,在JAVA中提供了多种参数来实现精度的不同控制方式。具体例子如下:
Java代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import java.math.BigDecimal;   
 
/**  
 * 与小数位精度(四舍五入等)相关的一些常用工具方法.  
 *   
 * float/double的精度取值方式分为以下几种: <br>  
 * java.math.BigDecimal.ROUND_UP <br>  
 * java.math.BigDecimal.ROUND_DOWN <br>  
 * java.math.BigDecimal.ROUND_CEILING <br>  
 * java.math.BigDecimal.ROUND_FLOOR <br>  
 * java.math.BigDecimal.ROUND_HALF_UP<br>  
 * java.math.BigDecimal.ROUND_HALF_DOWN <br>  
 * java.math.BigDecimal.ROUND_HALF_EVEN <br>  
 *   
 * @author stephen  
 * @version 1.0.0  
 */  
public final class RoundTool {   
 
    /**  
     * 对double数据进行取精度.  
     * <p>  
     * For example: <br>  
     * double value = 100.345678; <br>  
     * double ret = round(value,4,BigDecimal.ROUND_HALF_UP); <br>  
     * ret为100.3457 <br>  
     *   
     * @param value  
     *            double数据.  
     * @param scale  
     *            精度位数(保留的小数位数).  
     * @param roundingMode  
     *            精度取值方式.  
     * @return 精度计算后的数据.  
     */  
    public static double round(double value, int scale, int roundingMode) {   
        BigDecimal bd = new BigDecimal(value);   
        bd = bd.setScale(scale, roundingMode);   
        double d = bd.doubleValue();   
        bd = null;   
        return d;   
    }   
 
    /**  
     * 测试用的main方法.  
     *   
     * @param argc  
     *            运行参数.  
     */  
    public static void main(String[] argc) {   
        //下面都以保留2位小数为例   
 
        //ROUND_UP   
        //只要第2位后面存在大于0的小数,则第2位就+1   
        System.out.println(round(12.3401,2,BigDecimal.ROUND_UP));//12.35   
        System.out.println(round(-12.3401,2,BigDecimal.ROUND_UP));//-12.35   
        //ROUND_DOWN   
        //与ROUND_UP相反   
        //直接舍弃第2位后面的所有小数   
        System.out.println(round(12.349,2,BigDecimal.ROUND_DOWN));//12.34   
        System.out.println(round(-12.349,2,BigDecimal.ROUND_DOWN));//-12.34   
        //ROUND_CEILING   
        //如果数字>0 则和ROUND_UP作用一样   
        //如果数字<0 则和ROUND_DOWN作用一样   
        System.out.println(round(12.3401,2,BigDecimal.ROUND_CEILING));//12.35   
        System.out.println(round(-12.349,2,BigDecimal.ROUND_CEILING));//-12.34   
        //ROUND_FLOOR   
        //如果数字>0 则和ROUND_DOWN作用一样   
        //如果数字<0 则和ROUND_UP作用一样   
        System.out.println(round(12.349,2,BigDecimal.ROUND_FLOOR));//12.34   
        System.out.println(round(-12.3401,2,BigDecimal.ROUND_FLOOR));//-12.35   
        //ROUND_HALF_UP [这种方法最常用]   
        //如果第3位数字>=5,则第2位数字+1   
        //备注:只看第3位数字的值,不会考虑第3位之后的小数的   
        System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_UP));//12.35   
        System.out.println(round(12.3449,2,BigDecimal.ROUND_HALF_UP));//12.34   
        System.out.println(round(-12.345,2,BigDecimal.ROUND_HALF_UP));//-12.35   
        System.out.println(round(-12.3449,2,BigDecimal.ROUND_HALF_UP));//-12.34   
        //ROUND_HALF_DOWN   
        //如果第3位数字>=5,则做ROUND_UP   
        //如果第3位数字<5,则做ROUND_DOWN   
        System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_DOWN));//12.35   
        System.out.println(round(12.3449,2,BigDecimal.ROUND_HALF_DOWN));//12.34   
        System.out.println(round(-12.345,2,BigDecimal.ROUND_HALF_DOWN));//-12.35   
        System.out.println(round(-12.3449,2,BigDecimal.ROUND_HALF_DOWN));//-12.34   
        //ROUND_HALF_EVEN   
        //如果第3位是偶数,则做ROUND_HALF_DOWN   
        //如果第3位是奇数,则做ROUND_HALF_UP   
        System.out.println(round(12.346,2,BigDecimal.ROUND_HALF_EVEN));//12.35   
        System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_EVEN));//12.35   
    }   
}

这篇文章算说的比较详细的了,供参考。

差..好文!! (还没评价)
Loading ... Loading ...

Leave a Message

2 Messages

您好,请问对于第一个问题,
一个小数,例如1.7777777,或者1.3333333,不管后面的位数是多少,只保留到小数点后第二位,但是不是四舍五入,1.7777777处理后就是1.77,1.3333333处理后就是1.33
能否考虑用乘100再取整作呢?

Hi, tiezhen,

你的意思是小数先乘以100,取整,再除以100是这意思么?应该是ok滴:)

谢谢你的新思路~~~

 
 

RSS feed for comments on this post. TrackBack URI

Leave a Message