-2

I am using following code to round down the decimal number

private float roundOffTwoDigits(float number) {
    DecimalFormat toTheFormat = new DecimalFormat("0.0");
    toTheFormat.setRoundingMode(RoundingMode.DOWN);
    number = Float.valueOf(toTheFormat.format(number));
    return number;
}

Now there are the output I am getting

Input Output

2.2 > 2.2

2.21 > 2.2

2.28 > 2.2

2.4 > 2.4

2.6 > 2.5(Why 2.5 it should be 2.6)

2.8 > 2.7(Why 2.7 it should be 2.8)

So even number after decimal place and if it is more than 5 it is decreasing the value which should not happen.

Somebody marked my quesion duplicate with this question here Is floating point math broken?, I am not sure why ?

That question is not at all related to java and android and not having answers and discussion I was expecting.

Community
  • 1
  • 1
Piyush Agarwal
  • 25,608
  • 8
  • 98
  • 111
  • 1
    possible duplicate of [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – phuclv Sep 15 '15 at 15:41
  • Sorry, I am not finding my answer there, that question is not related to java at all and I don't know how you found it duplicate, not a single byte is related to question I have asked. – Piyush Agarwal Sep 15 '15 at 19:20
  • It's language agnostic, did you read the tags? And it explains why the binary floating-point value is not like one expected – phuclv Sep 16 '15 at 01:58
  • Hi but how can I get to know that was causing the issue , my simply point is that is not the question I asked and not helping me. I got good comments and answers on my question. – Piyush Agarwal Sep 16 '15 at 02:51

3 Answers3

5

The method has rounded correctly. 2.6 cannot be represented exactly as a float. When you write float a = 2.6F;, a is really

2.599999904632568359375

To do this correctly you should dispense with float completely, and do it using BigDecimal and its String constructor.

Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
  • Then why not for 2.4 ? – Piyush Agarwal Sep 15 '15 at 14:58
  • 1
    `2.4` cannot be represented exactly as a `float` either. It just happens that the true value of `2.4F` is `2.400000095367431640625` rather than a value just under `2.4`. You can find out these numbers yourself by doing `System.out.println(new BigDecimal(2.4F));`. – Paul Boddington Sep 15 '15 at 15:00
  • Ya I know that, is it expected behavior, any reason why java is biased ? – Piyush Agarwal Sep 15 '15 at 15:02
  • as you can see from http://docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html the RoundingMode accepts only int, so if you pass a float the problem is the one @PaulBoddington said – Pier Giorgio Misley Sep 15 '15 at 15:04
  • 3
    @pyus13 It has nothing to do with Java. Floating point arithmetic plagues all languages. Basically if you have a fraction `a/b` in its simplest form, it will not be an exact floating-point value unless `b` is a power of `2`. So `1.25` is a `float` as it is `5/4` but `3.7` is not as it is `37/10` and `10` is not a power of `2`. I don't think there's any simple logic to whether a floating point value will be just below, or just above the number you expect. – Paul Boddington Sep 15 '15 at 15:06
  • similarly the nearest to 2.2 in single precision is [2.2000000476837158203125E0](http://www.binaryconvert.com/result_float.html?decimal=050046050) – phuclv Sep 15 '15 at 15:46
0

It sounds like you want to add a Math.floor(). This will make your code always round to the highest value.

VirtualProdigy
  • 1,637
  • 1
  • 20
  • 40
0

You can use a workaround, since Paul explained perfectly all the motivations, you cann add a control:

private float roundOffTwoDigits(float number) {
    DecimalFormat toTheFormat = new DecimalFormat("0.0");
    toTheFormat.setRoundingMode(RoundingMode.DOWN);
    float roundedNumber = Float.valueOf(toTheFormat.format(number));
    //add a control to check if the code was wrongly rounded
    if((number - roundedNumber) >= 0,1){
        roundedNumber += 0,1
    }
    return roundedNumber;
}

in this way if the number was rounded to much you will have the correct result. I know, it's only a workaround but it should work

EDIT i wrote with one more decimal, fixed

Pier Giorgio Misley
  • 5,305
  • 4
  • 27
  • 66