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

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

Posted by: admin November 30, 2017 Leave a comment

Questions:

This question already has an answer here:

Answers:

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

Questions:
Answers:

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

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

Questions:
Answers:

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

Questions:
Answers:

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

Questions:
Answers:

Here is a simple one-line solution

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

Questions:
Answers:
//by importing Decimal format we can do...

import java.util.Scanner;
import java.text.DecimalFormat;
public class Average
{
public static void main(String[] args)
{
int sub1,sub2,sub3,total;
Scanner in = new Scanner(System.in);
System.out.print("Enter Subject 1 Marks : ");
sub1 = in.nextInt();
System.out.print("Enter Subject 2 Marks : ");
sub2 = in.nextInt();
System.out.print("Enter Subject 3 Marks : ");
sub3 = in.nextInt();
total = sub1 + sub2 + sub3;
System.out.println("Total Marks of Subjects = " + total);
res = (float)total;
average = res/3;
System.out.println("Before Rounding Decimal.. Average = " +average +"%");
DecimalFormat df = new DecimalFormat("###.##");
System.out.println("After Rounding Decimal.. Average = " +df.format(average)+"%");
}
}
/* Output
Enter Subject 1 Marks : 72
Enter Subject 2 Marks : 42
Enter Subject 3 Marks : 52
Total Marks of Subjects = 166
Before Rounding Decimal.. Average = 55.333332%
After Rounding Decimal.. Average = 55.33%
*/

/* Output
Enter Subject 1 Marks : 98
Enter Subject 2 Marks : 88
Enter Subject 3 Marks : 78
Total Marks of Subjects = 264
Before Rounding Decimal.. Average = 88.0%
After Rounding Decimal.. Average = 88%
*/

/* You can Find Avrerage values in two ouputs before rounding average
And After rounding Average..*/