使用ROUND_HALF_UP,BigDecimal不能很好地进行四舍五入

时间:2014-07-16 19:05:58

标签: java rounding bigdecimal

我正在创建一个应用程序来计算百分比的平均值,但问题是BigDecimal并不总是舍入平均值,例如,如果标记平均值为3.85,则比例1中的BigDecimal ROUND_HALF_UP应该舍入到3.9但它显示平均值像3.8一样,只发生了一些特定的时间,有时BigDecimal像4.5一样4.95它的好,但我不知道为什么会发生,问题出在哪里。这是一个示例代码,您可以看到问题:

import java.io.*;
import java.math.BigDecimal;


public class Main {

    public static void main(String[] args) throws IOException{
        InputStreamReader input = new InputStreamReader(System.in);
        BufferedReader buff = new BufferedReader (input);

        //temporal 
        float average=0;
        float mark1=0;
        float mark2=0;
        float percent1=0.75f;
        float percent2=0.25f;

        for(int i=0;i<1;i++){
        System.out.println("Enter mark 1 (75%) : ");
        mark1=Float.parseFloat(buff.readLine());

        }

        for(int i=0;i<1;i++){
            System.out.println("Enter mark 2 (25%): ");
            mark2=Float.parseFloat(buff.readLine());

            }

        average= ((mark1*percent1)+(mark2*percent2));
        // convert to BigDecimal
        BigDecimal bd = new BigDecimal(average);

        BigDecimal roundingMark = bd.setScale(1,
                BigDecimal.ROUND_HALF_UP);

        System.out.println(" the complete average is :"+average);
        System.out.println(" The rounding average is :"+roundingMark);
        }


}

你应该在第一个标记4.5和第二个标记1.9中输入结果为3.8并且应该是3.9

请原谅我的英语不好,非常感谢阅读:)

1 个答案:

答案 0 :(得分:2)

您应该使用BigDecimal进行计算,而不仅仅是舍入。

含义,mark1mark2percent1percent2average应为BigDecimal s。您在此处遇到的问题是precision problemfloat s不够精确,无法保证计算的准确性,因此您认为3.85实际上应该是3.849999999999。尝试打印bd,您的原始值为849999904632568359375(至少这是我的确切值)。

编辑,扩展:我刚刚想到你也可能误解了ROUND_HALF_UP的含义。我引用文档

  

舍入模式向&#34;最近邻居&#34;除非两个邻居都是等距的,在这种情况下会向上舍入。如果丢弃的分数≥0.5,则表现为ROUND_UP;否则,表现为ROUND_DOWN。请注意,这是我们大多数人在小学就读的四舍五入模式。

因此,总结精度问题,导致bd的实际值更接近3.8而不是3.9,以及ROUND_HALF_UP的预期行为,你应该现在有一个完整的结果解释。