如何在Java中将数字舍入到n位小数

1462
我想要的是一种将双精度浮点数转换为字符串的方法,该方法使用"四舍五入" - 即如果要舍入的小数为5,则始终向上舍入到下一个数字。这是大多数情况下人们预期的标准舍入方法。同时,只显示有效数字 - 即不应有任何尾随零。
我知道实现此功能的一种方法是使用String.format方法:
String.format("%.5g%n", 0.912385);

返回值:

0.91239

这很不错,但它总是显示带有5位小数的数字,即使它们并不重要:

String.format("%.5g%n", 0.912300);

返回:

0.91230

另一种方法是使用DecimalFormatter

DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);

返回:

0.91238

不过,正如您所看到的,这里使用的是"半偶数"舍入法。也就是说,如果前一个数字是偶数,则会将其向下舍入。我希望的是:

0.912385 -> 0.91239
0.912300 -> 0.9123

在Java中实现这一目标的最佳方法是什么?

39个回答

1

非常简单的方法

public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    DecimalFormat deciFormat = new DecimalFormat();
    deciFormat.setMaximumFractionDigits(places);
    String newValue = deciFormat.format(value);

    return Double.parseDouble(newValue);

}

double a = round(12.36545, 2);

这是一个非常糟糕的方法。字符串不是双精度数。 - Panagiotis Kanavos

1
为了在最后一位保留零直到第五位。
DecimalFormat decimalFormatter = new DecimalFormat("#.00000");
decimalFormatter.format(0.350500); // result 0.350500
为避免小数点后出现多余的0,最多保留5位数字。
DecimalFormat decimalFormatter= new DecimalFormat("#.#####");
decimalFormatter.format(0.350500); // result o.3505

1
以下方法可用于需要使用double的情况。
double getRandom(int decimalPoints) {
    double a = Math.random();
    int multiplier = (int) Math.pow(10, decimalPoints);
    int b = (int) (a * multiplier);
    return b / (double) multiplier;
}

例如 getRandom(2)

0

其中 dp = 你想要的小数位数, 而 value 是一个双精度浮点数。

    double p = Math.pow(10d, dp);

    double result = Math.round(value * p)/p;

1
使用这个代替,对于value = 1.005dp = 2,产生1.0 - Matthias Braun
没关系,马特,你的例子是无效的。因为1.005在浮点双精度中无法表示。它必须存储在1.005的上方或下方,即当您编译时,它被存储为双精度:1.0049998(它不像您让读者相信的那样以十进制形式存储在编译后的代码中)。艾姆是正确的,他将值存储为浮点双精度,其中像你这样的边缘情况是微不足道的。如果是这样,那么您将使用3dp然后将其转换为十进制,然后执行十进制舍入函数,就像您发布的链接一样。 - hamish
1
@hamish,我没有看到Matthias“让读者相信”这个值被编译为十进制的地方。不要替别人说话。 - user207421

0

这是我发现的最简单的方法,可以仅显示两位小数。

double x = 123.123;
System.out.printf( "%.2f", x );

0
请记住,String.format()和DecimalFormat使用默认语言环境生成字符串。因此,它们可能会使用点或逗号作为整数和小数部分之间的分隔符来编写格式化数字。为确保舍入的字符串以所需的格式呈现,请使用java.text.NumberFormat:
  Locale locale = Locale.ENGLISH;
  NumberFormat nf = NumberFormat.getNumberInstance(locale);
  // for trailing zeros:
  nf.setMinimumFractionDigits(2);
  // round to 2 digits:
  nf.setMaximumFractionDigits(2);

  System.out.println(nf.format(.99));
  System.out.println(nf.format(123.567));
  System.out.println(nf.format(123.0));

将以英语区域设置打印(无论您的区域设置是什么): 0.99 123.57 123.00

该示例取自Farenda - 如何正确将double转换为String


0

比较小数点位数有一个简单的方法。 我们可以使用强制类型转换,而不是DecimalFormat、Math或BigDecimal!

这里是示例:

public static boolean threeDecimalPlaces(double value1, double value2){
    boolean isEqual = false;
    // value1 = 3.1756 
    // value2 = 3.17
    //(int) (value1 * 1000) = 3175
    //(int) (value2 * 1000) = 3170

    if ((int) (value1 * 1000) == (int) (value2 * 1000)){
        areEqual = true;
    }

    return isEqual;
}

0

Math.round解决方案在尝试四舍五入到负小数位时存在问题。请考虑以下代码:

long l = 10;
for(int dp = -1; dp > -10; --dp) {
    double mul = Math.pow(10,dp);
    double res = Math.round(l * mul) / mul;
    System.out.println(""+l+" rounded to "+dp+" dp = "+res);
    l *=10;
}

这里是结果

10 rounded to -1 dp = 10.0
100 rounded to -2 dp = 100.0
1000 rounded to -3 dp = 1000.0
10000 rounded to -4 dp = 10000.0
100000 rounded to -5 dp = 99999.99999999999
1000000 rounded to -6 dp = 1000000.0
10000000 rounded to -7 dp = 1.0E7
100000000 rounded to -8 dp = 1.0E8
1000000000 rounded to -9 dp = 9.999999999999999E8

-5个小数位的问题发生在将1除以1.0E-5时,由于其不精确。

这可以通过以下方式解决:

double mul = Math.pow(10,dp);
double res;
if(dp < 0 ) {
    double div = Math.pow(10,-dp);
    res = Math.round(l * mul) *div;
} else {
    res = Math.round(l * mul) / mul;
}

但这是使用BigDecimal方法的另一个原因。


-1

如果你考虑5或n个小数位,也许这个答案可以解决你的问题。

    double a = 123.00449;
    double roundOff1 = Math.round(a*10000)/10000.00;
    double roundOff2 = Math.round(roundOff1*1000)/1000.00;
    double roundOff = Math.round(roundOff2*100)/100.00;

    System.out.println("result:"+roundOff);

输出结果为:123.01
这可以通过循环和递归函数来解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接