user3207976
user3207976

Reputation: 33

BigDecimal is not rounding good with ROUND_HALF_UP

I am creating an app to calculate a mark average with percents, but the problem is that BigDecimal not always rounding the average, for example if the mark average is 3.85 BigDecimal ROUND_HALF_UP in scale 1 should round to 3.9 but it show the average like 3.8, that happened with only some specific times, sometimes BigDecimal round 4.95 like 5.0 and its good, but I don't know why happened and where is the problem. This is an example code for you can see the problem:

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);
        }


}

You should put in the first mark 4.5 and in the second mark 1.9 the result will be 3.8 and should be 3.9

Please excuse my for bad English and thank so much for read :)

Upvotes: 0

Views: 1500

Answers (1)

ThanksForAllTheFish
ThanksForAllTheFish

Reputation: 7241

You should use BigDecimal for calculations, not just for rounding.

Meaning, mark1, mark2, percent1, percent2 and average should be BigDecimals. The issue you are facing here is a precision problem: floats are not precise enough to guarantee exactness of computation, so what you think should be 3.85 actually is 3.849999999999. Try to print bd and you will its original value to be 849999904632568359375 (at least this is the exact value for me).

EDIT, expansion: it just occurred to me you may also misunderstanding the meaning of ROUND_HALF_UP. I cite from the documentation

Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up. Behaves as for ROUND_UP if the discarded fraction is ≥ 0.5; otherwise, behaves as for ROUND_DOWN. Note that this is the rounding mode that most of us were taught in grade school.

So, summing the precision issue, causing the real value of bd to be closer to 3.8 than to 3.9, and the intended behavior of ROUND_HALF_UP, you should have now a complete explanation of your results.

Upvotes: 2

Related Questions