关于java:将浮点数舍入为2位小数的最佳做法是什么?

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

本问题已经有最佳答案,请猛点这里访问。

我正在使用Eclipse+Android SDK。

我需要把一个浮点值四舍五入到2位小数。我通常使用下一个"技巧"使用数学库。

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

但我觉得这不是最好的方法。

是否有一个库来执行这些类型的操作?

事先谢谢。


2年前我在Java中使用统计学,我仍然有一个函数的代码,它允许你把一个数字和你想要的小数相结合。现在你需要两个,但也许你想用3来比较结果,这个函数给了你这个自由。

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 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();
}

你需要决定你是想把球打进还是打进。在我的示例代码中,我将进行四舍五入。

希望它有帮助。

编辑

如果要在小数为零时保留小数位数(我猜这只是为了向用户显示),只需将函数类型从float更改为bigdecimal,如下所示:

1
2
3
4
5
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;
}

然后这样调用函数:

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

这将打印:

1
2.30


让我们测试3种方法:1)

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

2)

1
2
3
4
5
6
7
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)

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

数字是0.23453F我们将测试每个方法100000次迭代。结果:时间1 - 18毫秒时间2 - 1毫秒时间3 - 378毫秒在笔记本电脑上测试Intel i3-3310M CPU 2.4GHz


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


这是一个较短的实现,与@jav_rock相比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
   /**
     * 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

我尝试支持@ivan stin优秀第二种方法的-ve值。(他的方法主要归功于@ivan stin)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}

下面是我试过的测试案例。如果这不涉及其他案件,请告诉我。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@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);
}

这是一个简单的单行解决方案

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//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..*/