Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best practice to round a float to 2 decimals? [duplicate]

Tags:

java

android

math

People also ask

How do you keep a float up to 2 decimal places?

format("%. 2f", 1.23456); This will format the floating point number 1.23456 up-to 2 decimal places, because we have used two after decimal point in formatting instruction %.

What are the rules for rounding to 2 decimal places?

Rounding a decimal number to two decimal places is the same as rounding it to the hundredths place, which is the second place to the right of the decimal point. For example, 2.83620364 can be round to two decimal places as 2.84, and 0.7035 can be round to two decimal places as 0.70.


I was working with statistics in Java 2 years ago and I still got the codes of a function that allows you to round a number to the number of decimals that you want. Now you need two, but maybe you would like to try with 3 to compare results, and this function gives you this freedom.

/**
* Round to certain number of decimals
* 
* @param d
* @param decimalPlace
* @return
*/
public static float round(float d, int decimalPlace) {
    BigDecimal bd = new BigDecimal(Float.toString(d));
    bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
    return bd.floatValue();
}

You need to decide if you want to round up or down. In my sample code I am rounding up.

Hope it helps.

EDIT

If you want to preserve the number of decimals when they are zero (I guess it is just for displaying to the user) you just have to change the function type from float to BigDecimal, like this:

public static BigDecimal round(float d, int decimalPlace) {
    BigDecimal bd = new BigDecimal(Float.toString(d));
    bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);       
    return bd;
}

And then call the function this way:

float x = 2.3f;
BigDecimal result;
result=round(x,2);
System.out.println(result);

This will print:

2.30

Let's test 3 methods:
1)

public static double round1(double value, int scale) {
    return Math.round(value * Math.pow(10, scale)) / Math.pow(10, scale);
}

2)

public static float round2(float number, int scale) {
    int pow = 10;
    for (int i = 1; i < scale; i++)
        pow *= 10;
    float tmp = number * pow;
    return ( (float) ( (int) ((tmp - (int) tmp) >= 0.5f ? tmp + 1 : tmp) ) ) / pow;
}

3)

public static float round3(float d, int decimalPlace) {
    return BigDecimal.valueOf(d).setScale(decimalPlace, BigDecimal.ROUND_HALF_UP).floatValue();
}



Number is 0.23453f
We'll test 100,000 iterations each method.

Results:
Time 1 - 18 ms
Time 2 - 1 ms
Time 3 - 378 ms


Tested on laptop
Intel i3-3310M CPU 2.4GHz


double roundTwoDecimals(double d) {
  DecimalFormat twoDForm = new DecimalFormat("#.##");
  return Double.valueOf(twoDForm.format(d));
}

Here is a shorter implementation comparing to @Jav_Rock's

   /**
     * Round to certain number of decimals
     * 
     * @param d
     * @param decimalPlace the numbers of decimals
     * @return
     */

    public static float round(float d, int decimalPlace) {
         return BigDecimal.valueOf(d).setScale(decimalPlace,BigDecimal.ROUND_HALF_UP).floatValue();
    }



    System.out.println(round(2.345f,2));//two decimal digits, //2.35

I've tried to support the -ve values for @Ivan Stin excellent 2nd method. (Major credit goes to @Ivan Stin for his method)

public static float round(float value, int scale) {
    int pow = 10;
    for (int i = 1; i < scale; i++) {
        pow *= 10;
    }
    float tmp = value * pow;
    float tmpSub = tmp - (int) tmp;

    return ( (float) ( (int) (
            value >= 0
            ? (tmpSub >= 0.5f ? tmp + 1 : tmp)
            : (tmpSub >= -0.5f ? tmp : tmp - 1)
            ) ) ) / pow;

    // Below will only handles +ve values
    // return ( (float) ( (int) ((tmp - (int) tmp) >= 0.5f ? tmp + 1 : tmp) ) ) / pow;
}

Below are the tests cases I've tried. Please let me know if this is not addressing any other cases.

@Test
public void testFloatRound() {
    // +ve values
    Assert.assertEquals(0F, NumberUtils.round(0F), 0);
    Assert.assertEquals(1F, NumberUtils.round(1F), 0);
    Assert.assertEquals(23.46F, NumberUtils.round(23.4567F), 0);
    Assert.assertEquals(23.45F, NumberUtils.round(23.4547F), 0D);
    Assert.assertEquals(1.00F, NumberUtils.round(0.49999999999999994F + 0.5F), 0);
    Assert.assertEquals(123.12F, NumberUtils.round(123.123F), 0);
    Assert.assertEquals(0.12F, NumberUtils.round(0.123F), 0);
    Assert.assertEquals(0.55F, NumberUtils.round(0.55F), 0);
    Assert.assertEquals(0.55F, NumberUtils.round(0.554F), 0);
    Assert.assertEquals(0.56F, NumberUtils.round(0.556F), 0);
    Assert.assertEquals(123.13F, NumberUtils.round(123.126F), 0);
    Assert.assertEquals(123.15F, NumberUtils.round(123.15F), 0);
    Assert.assertEquals(123.17F, NumberUtils.round(123.1666F), 0);
    Assert.assertEquals(123.46F, NumberUtils.round(123.4567F), 0);
    Assert.assertEquals(123.87F, NumberUtils.round(123.8711F), 0);
    Assert.assertEquals(123.15F, NumberUtils.round(123.15123F), 0);
    Assert.assertEquals(123.89F, NumberUtils.round(123.8909F), 0);
    Assert.assertEquals(124.00F, NumberUtils.round(123.9999F), 0);
    Assert.assertEquals(123.70F, NumberUtils.round(123.7F), 0);
    Assert.assertEquals(123.56F, NumberUtils.round(123.555F), 0);
    Assert.assertEquals(123.00F, NumberUtils.round(123.00F), 0);
    Assert.assertEquals(123.50F, NumberUtils.round(123.50F), 0);
    Assert.assertEquals(123.93F, NumberUtils.round(123.93F), 0);
    Assert.assertEquals(123.93F, NumberUtils.round(123.9312F), 0);
    Assert.assertEquals(123.94F, NumberUtils.round(123.9351F), 0);
    Assert.assertEquals(123.94F, NumberUtils.round(123.9350F), 0);
    Assert.assertEquals(123.94F, NumberUtils.round(123.93501F), 0);
    Assert.assertEquals(99.99F, NumberUtils.round(99.99F), 0);
    Assert.assertEquals(100.00F, NumberUtils.round(99.999F), 0);
    Assert.assertEquals(100.00F, NumberUtils.round(99.9999F), 0);

    // -ve values
    Assert.assertEquals(-123.94F, NumberUtils.round(-123.93501F), 0);
    Assert.assertEquals(-123.00F, NumberUtils.round(-123.001F), 0);
    Assert.assertEquals(-0.94F, NumberUtils.round(-0.93501F), 0);
    Assert.assertEquals(-1F, NumberUtils.round(-1F), 0);
    Assert.assertEquals(-0.50F, NumberUtils.round(-0.50F), 0);
    Assert.assertEquals(-0.55F, NumberUtils.round(-0.55F), 0);
    Assert.assertEquals(-0.55F, NumberUtils.round(-0.554F), 0);
    Assert.assertEquals(-0.56F, NumberUtils.round(-0.556F), 0);
    Assert.assertEquals(-0.12F, NumberUtils.round(-0.1234F), 0);
    Assert.assertEquals(-0.12F, NumberUtils.round(-0.123456789F), 0);
    Assert.assertEquals(-0.13F, NumberUtils.round(-0.129F), 0);
    Assert.assertEquals(-99.99F, NumberUtils.round(-99.99F), 0);
    Assert.assertEquals(-100.00F, NumberUtils.round(-99.999F), 0);
    Assert.assertEquals(-100.00F, NumberUtils.round(-99.9999F), 0);
}

Here is a simple one-line solution

((int) ((value + 0.005f) * 100)) / 100f