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

JavaAndroidMath

Java Problem Overview


I'm using eclipse + Android SDK.

I need to round a float value to 2 decimals. I usually use the next "trick" using Math library.

float accelerometerX = accelerometerX * 100;
	accelerometerX = round(accelerometerX);
	Log.d("Test","" + accelerometerX/100);

But I feel it is not the best way to do it.

Is there a library to do these type of operations?

Java Solutions


Solution 1 - Java

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

Solution 2 - Java

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

Solution 3 - Java

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

Solution 4 - Java

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

Solution 5 - Java

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

Solution 6 - Java

Here is a simple one-line solution

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

Solution 7 - Java

//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..*/

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionvgonisanzView Question on Stackoverflow
Solution 1 - JavaJav_RockView Answer on Stackoverflow
Solution 2 - JavaIvan StinView Answer on Stackoverflow
Solution 3 - JavaShadowView Answer on Stackoverflow
Solution 4 - JavaJaskeyLamView Answer on Stackoverflow
Solution 5 - JavamanikantaView Answer on Stackoverflow
Solution 6 - JavaIlya BystrovView Answer on Stackoverflow
Solution 7 - JavaSandeep16View Answer on Stackoverflow