如何四舍五入一个数字n小数位在Java

我想要的是一个方法,将一个双精度转换为一个字符串,使用半向上方法-即,如果要四舍五入的小数是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.912390.912300 -> 0.9123

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

2000754 次浏览

假设valuedouble,你可以这样做:

(double)Math.round(value * 100000d) / 100000d

这是5位精度。零的数量表示小数的数量。

double myNum = .912385;int precision = 10000; //keep 4 digitsmyNum= Math.floor(myNum * precision +.5)/precision;

使用#0,显式设置#1以处理半偶数轮的问题,然后使用所需输出的格式模式。

示例:

DecimalFormat df = new DecimalFormat("#.####");df.setRoundingMode(RoundingMode.CEILING);for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {Double d = n.doubleValue();System.out.println(df.format(d));}

给出输出:

12123.12350.230.12341234.2125

编辑:最初的答案并没有解决double值的精度问题。如果你不太关心它是向上舍入还是向下舍入,这很好。但是如果你想要准确的四舍五入,那么你需要考虑值的预期精度。浮点值在内部有一个二进制表示。这意味着像2.7735这样的值在内部实际上并没有这个精确的值。它可以稍大或稍小。如果内部值稍小,那么它不会四舍五入到2.7740。为了纠正这种情况,你需要意识到你正在使用的值的准确性,并在四舍五入之前添加或减去该值。例如,当您知道您的值精确到6位数字时,然后要将中途值向上舍入,请将该精度添加到值中:

Double d = n.doubleValue() + 1e-6;

要向下舍入,减去精度。

您也可以使用

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

以确保你有尾随的0。

new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);

要得到字符串,只需调用BigDecimaltoString方法,或者调用toPlainString方法Java5+作为纯格式字符串。

示例程序:

package trials;import java.math.BigDecimal;
public class Trials {
public static void main(String[] args) {int yourScale = 10;System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));}

Real的Java如何员额这个解决方案,它也兼容Java1.6之前的版本。

BigDecimal bd = new BigDecimal(Double.toString(d));bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);return bd.doubleValue();

更新:BigDecimal.ROUND_HALF_UP已弃用-使用RoundingMode

BigDecimal bd = new BigDecimal(Double.toString(number));bd = bd.setScale(decimalPlaces, RoundingMode.HALF_UP);return bd.doubleValue();

假设你有

double d = 9232.129394d;

你可以使用#0

BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);d = bd.doubleValue();

或没有BigDecimal

d = Math.round(d*100)/100.0d;

两种解决方案d == 9232.13

您可以使用以下实用方法-

public static double round(double valueToRound, int numberOfDecimalPlaces){double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);double interestedInZeroDPs = valueToRound * multipicationFactor;return Math.round(interestedInZeroDPs) / multipicationFactor;}

@Milhous:舍入的十进制格式非常好:

您也可以使用

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

以确保你有尾随的0。

我想补充一点,这种方法非常擅长提供实际的数字,舍入机制-不仅在视觉上,而且在处理时。

假设:您必须在GUI中实现舍入机制程序。只需更改结果输出的准确性/精确度更改插入符号格式(即括号内)。这样:

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

将作为输出返回:0.912385

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

将作为输出返回:0.91239

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

将作为输出返回:0.9124

[编辑:如果插入符号格式是这样的(“#0.############")输入一个小数,例如3.1415926,为了参数的缘故,DecimalFormat不会产生任何垃圾(例如尾随零),并将返回:3.1415926…如果你有这种倾向。当然,这有点冗长对于一些开发人员的喜好-但是嘿,它的内存占用量很低

所以本质上,DecimalFormat的美妙之处在于它同时处理字符串外观-以及舍入精度设置的级别。因此:你以一个代码实现的价格获得两个好处。;)

如果您真的想要十进制数字用于计算(而不仅仅是用于输出),请不要使用基于二进制的浮点格式,如双精度。

Use BigDecimal or any other decimal-based format.

我确实使用BigDecimal进行计算,但请记住,它取决于在我的大多数实现中,我发现解析来自双精度或整数到Long足以进行非常大的数字计算。

事实上,我最近使用parsed-to-Long来获得准确的表示(与十六进制结果相反)在GUI中,对于像 ################################# 字符一样大的数字(作为示例)。

下面的代码片段显示了如何显示n位数字。诀窍是将变量pp设置为1,后跟n个零。在下面的示例中,变量pp值有5个零,因此将显示5位数字。

double pp = 10000;
double myVal = 22.268699999999967;String needVal = "22.2687";
double i = (5.0/pp);
String format = "%10.4f";String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();

您可以使用DecimalFormat类。

double d = 3.76628729;
DecimalFormat newFormat = new DecimalFormat("#.##");double twoDecimal =  Double.valueOf(newFormat.format(d));

正如其他一些人所指出的,正确的答案是使用DecimalFormatBigDecimal。浮点数不会小数位,因此您首先不可能将其舍入/截断为特定数量。您必须使用小数基数,这就是这两个类所做的。

我发布以下代码作为本线程中以及整个StackOverflow(以及其他地方)建议乘法、截断和除法的所有答案的反例。这种技术的倡导者有责任解释为什么以下代码在超过92%的情况下会产生错误的输出。

public class RoundingCounterExample{
static float roundOff(float x, int position){float a = x;double temp = Math.pow(10.0, position);a *= temp;a = Math.round(a);return (a / (float)temp);}
public static void main(String[] args){float a = roundOff(0.0009434f,3);System.out.println("a="+a+" (a % .001)="+(a % 0.001));int count = 0, errors = 0;for (double x = 0.0; x < 1; x += 0.0001){count++;double d = x;int scale = 2;double factor = Math.pow(10, scale);d = Math.round(d * factor) / factor;if ((d % 0.01) != 0.0){System.out.println(d + " " + (d % 0.01));errors++;}}System.out.println(count + " trials " + errors + " errors");}}

此程序的输出:

10001 trials 9251 errors

编辑:为了解决下面的一些评论,我使用BigDecimalnew MathContext(16)重做了测试循环的模数部分,如下所示:

public static void main(String[] args){int count = 0, errors = 0;int scale = 2;double factor = Math.pow(10, scale);MathContext mc = new MathContext(16, RoundingMode.DOWN);for (double x = 0.0; x < 1; x += 0.0001){count++;double d = x;d = Math.round(d * factor) / factor;BigDecimal bd = new BigDecimal(d, mc);bd = bd.remainder(new BigDecimal("0.01"), mc);if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0){System.out.println(d + " " + bd);errors++;}}System.out.println(count + " trials " + errors + " errors");}

结果:

10001 trials 4401 errors

试试这个:org.apache.commons.math3.util.Precision.round(双x,int比例)

见:http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html

Apache Commons数学库主页是:http://commons.apache.org/proper/commons-math/index.html

该方法的内部实现是:

public static double round(double x, int scale) {return round(x, scale, BigDecimal.ROUND_HALF_UP);}
public static double round(double x, int scale, int roundingMethod) {try {return (new BigDecimal(Double.toString(x)).setScale(scale, roundingMethod)).doubleValue();} catch (NumberFormatException ex) {if (Double.isInfinite(x)) {return x;} else {return Double.NaN;}}}

其中dp=你想要的小数位,是双精度的

    double p = Math.pow(10d, dp);
double result = Math.round(value * p)/p;

您可以使用BigDecimal

BigDecimal value = new BigDecimal("2.3");value = value.setScale(0, RoundingMode.UP);BigDecimal value1 = new BigDecimal("-2.3");value1 = value1.setScale(0, RoundingMode.UP);System.out.println(value + "n" + value1);

参考:http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/

如果您使用DecimalFormatdouble转换为String,则非常简单:

DecimalFormat formatter = new DecimalFormat("0.0##");formatter.setRoundingMode(RoundingMode.HALF_UP);
double num = 1.234567;return formatter.format(num);

有几个RoundingMode枚举值可供选择,具体取决于您需要的行为。

如果您希望结果为String,以下是您可以使用的摘要:

  1. 十进制格式#set四舍五入模式()

    DecimalFormat df = new DecimalFormat("#.#####");df.setRoundingMode(RoundingMode.HALF_UP);String str1 = df.format(0.912385)); // 0.91239
  2. BigDecimal#setScale()

    String str2 = new BigDecimal(0.912385).setScale(5, BigDecimal.ROUND_HALF_UP).toString();

Here is a suggestion of what libraries you can use if you want double as a result. I wouldn't recommend it for string conversion, though, as double may not be able to represent what you want exactly (see e.g. here):

  1. Precision from Apache Commons Math

    double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
  2. Functions from Colt

    double rounded = Functions.round(0.00001).apply(0.912385)
  3. Utils from Weka

    double rounded = Utils.roundDouble(0.912385, 5)

我同意选择的答案使用DecimalFormat-或替代BigDecimal

请先阅读下面的更新

但是,如果您想要舍入双精度值并获得double值结果,您可以使用上面提到的org.apache.commons.math3.util.Precision.round(..)。实现使用BigDecimal,速度慢并创建垃圾。

decimal4j库中的DoubleRounder实用程序提供了一个类似但快速且无垃圾的方法:

 double a = DoubleRounder.round(2.0/3.0, 3);double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);double c = DoubleRounder.round(1000.0d, 17);double d = DoubleRounder.round(90080070060.1d, 9);System.out.println(a);System.out.println(b);System.out.println(c);System.out.println(d);

将输出

 0.6670.6661000.09.00800700601E10

https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility

披露:我参与了decimal4j项目。

更新:正如@iForek指出的那样,DoubleRounder有时会返回违反直觉的结果。原因是它执行数学上正确的舍入。例如DoubleRounder.round(256.025d, 2)将被向下舍入到256.02,因为表示为256.025d的双精度值比有理数256.025小一些,因此将被向下舍入。

备注:

  • 这种行为与BigDecimal(double)构造函数非常相似(但与使用字符串构造函数的valueOf(double)不同)。
  • 这个问题可以通过双舍入步骤来规避,首先达到更高的精度,但它很复杂,我不会在这里详细介绍

由于这些原因和上面提到的一切,我不能推荐使用DoubleRounder

以防有人仍然需要帮助。这个解决方案非常适合我。

private String withNoTrailingZeros(final double value, final int nrOfDecimals) {return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals,  BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
}

返回具有所需输出的 String

由于我在这个主题上没有找到完整的答案,我已经整理了一个应该正确处理这个问题的类,并支持:

  • 格式:轻松将双精度格式化为具有一定小数位数的字符串
  • 解析:将格式化的值解析回双精度
  • 区域设置:使用默认语言环境格式化和解析
  • 指数记数法:在某个阈值后开始使用指数表示法

用法很简单

(为了这个例子,我使用了一个自定义语言环境)

public static final int DECIMAL_PLACES = 2;
NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);
String value = formatter.format(9.319); // "9,32"String value2 = formatter.format(0.0000005); // "5,00E-7"String value3 = formatter.format(1324134123); // "1,32E9"
double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004double parsedValue2 = formatter.parse("0,002", 0); // 0.002double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345

这是课堂

import java.math.RoundingMode;import java.text.DecimalFormat;import java.text.DecimalFormatSymbols;import java.text.ParseException;import java.util.Locale;
public class NumberFormatter {
private static final String SYMBOL_INFINITE           = "\u221e";private static final char   SYMBOL_MINUS              = '-';private static final char   SYMBOL_ZERO               = '0';private static final int    DECIMAL_LEADING_GROUPS    = 10;private static final int    EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notationprivate static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation
private DecimalFormat decimalFormat;private DecimalFormat decimalFormatLong;private DecimalFormat exponentialFormat;
private char groupSeparator;
public NumberFormatter(int decimalPlaces) {configureDecimalPlaces(decimalPlaces);}
public void configureDecimalPlaces(int decimalPlaces) {if (decimalPlaces <= 0) {throw new IllegalArgumentException("Invalid decimal places");}
DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());separators.setMinusSign(SYMBOL_MINUS);separators.setZeroDigit(SYMBOL_ZERO);
groupSeparator = separators.getGroupingSeparator();
StringBuilder decimal = new StringBuilder();StringBuilder exponential = new StringBuilder("0.");
for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");}
for (int i = 0; i < decimalPlaces; i++) {decimal.append("#");exponential.append("0");}
exponential.append("E0");
decimalFormat = new DecimalFormat(decimal.toString(), separators);decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);exponentialFormat = new DecimalFormat(exponential.toString(), separators);
decimalFormat.setRoundingMode(RoundingMode.HALF_UP);decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);}
public String format(double value) {String result;if (Double.isNaN(value)) {result = "";} else if (Double.isInfinite(value)) {result = String.valueOf(SYMBOL_INFINITE);} else {double absValue = Math.abs(value);if (absValue >= 1) {if (absValue >= EXPONENTIAL_INT_THRESHOLD) {value = Math.floor(value);result = exponentialFormat.format(value);} else {result = decimalFormat.format(value);}} else if (absValue < 1 && absValue > 0) {if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {result = decimalFormat.format(value);if (result.equalsIgnoreCase("0")) {result = decimalFormatLong.format(value);}} else {result = exponentialFormat.format(value);}} else {result = "0";}}return result;}
public String formatWithoutGroupSeparators(double value) {return removeGroupSeparators(format(value));}
public double parse(String value, double defValue) {try {return decimalFormat.parse(value).doubleValue();} catch (ParseException e) {e.printStackTrace();}return defValue;}
private String removeGroupSeparators(String number) {return number.replace(String.valueOf(groupSeparator), "");}
}

请记住,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.99123.57123.00

该示例取自Farenda-如何正确将双精度转换为字符串

如果你考虑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.0<强>1
这可以用循环和递归函数来解决。

DecimalFormat是输出的最佳方式,但我不喜欢它。我总是这样做,因为它返回双精度值。所以我可以使用它而不仅仅是输出。

Math.round(selfEvaluate*100000d.0)/100000d.0;

Math.round(selfEvaluate*100000d.0)*0.00000d1;

如果您需要大的小数位值,您可以使用BigDecimal代替。无论如何.0很重要。没有它,0.33333d5的四舍五入返回0.33333,只允许9位数字。没有.0的第二个函数有0.30000返回0的问题。30000000000000004。

我来这里只是想要一个关于如何舍入一个数字的简单答案。这是提供这个的补充答案。

如何在Java中舍入一个数字

最常见的情况是使用Math.round()

Math.round(3.7) // 4

数字被舍入到最接近的整数。.5值被舍入。如果您需要不同的舍入行为,您可以使用其他Math函数之一。请参阅下面的比较。

如上所述,这四舍五入到最接近的整数。.5小数舍入。此方法返回int

Math.round(3.0); // 3Math.round(3.1); // 3Math.round(3.5); // 4Math.round(3.9); // 4
Math.round(-3.0); // -3Math.round(-3.1); // -3Math.round(-3.5); // -3 *** careful here ***Math.round(-3.9); // -4

cail

任何十进制值都向上舍入到下一个整数。它进入ciling。此方法返回double

Math.ceil(3.0); // 3.0Math.ceil(3.1); // 4.0Math.ceil(3.5); // 4.0Math.ceil(3.9); // 4.0
Math.ceil(-3.0); // -3.0Math.ceil(-3.1); // -3.0Math.ceil(-3.5); // -3.0Math.ceil(-3.9); // -3.0

地板

任何十进制值都会向下舍入到下一个整数。此方法返回double

Math.floor(3.0); // 3.0Math.floor(3.1); // 3.0Math.floor(3.5); // 3.0Math.floor(3.9); // 3.0
Math.floor(-3.0); // -3.0Math.floor(-3.1); // -4.0Math.floor(-3.5); // -4.0Math.floor(-3.9); // -4.0

rint

这类似于将十进制值舍入到最接近的整数。但是,与round不同,.5值舍入到偶数整数。此方法返回double

Math.rint(3.0); // 3.0Math.rint(3.1); // 3.0Math.rint(3.5); // 4.0 ***Math.rint(3.9); // 4.0Math.rint(4.5); // 4.0 ***Math.rint(5.5); // 6.0 ***
Math.rint(-3.0); // -3.0Math.rint(-3.1); // -3.0Math.rint(-3.5); // -4.0 ***Math.rint(-3.9); // -4.0Math.rint(-4.5); // -4.0 ***Math.rint(-5.5); // -6.0 ***

简洁的解决方案:

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

另见https://stackoverflow.com/a/22186845/212950感谢jpdymond提供这个。

编辑:添加了圆括号。将整个结果转换为双精度,而不仅仅是第一个参数!

如果您使用的是具有最小JDK的技术。这是一种没有任何Java库的方法:

double scale = 100000;double myVal = 0.912385;double rounded = (int)((myVal * scale) + 0.5d) / scale;

这是一个更好的函数,可以正确舍入像1.005这样的边缘情况。

简单地说,我们在四舍五入之前将最小的浮点值(=1 ulp;最后一个单位)添加到数字中。这将移动到数字之后的下一个可表示值,远离零。

这是一个测试它的小程序:ideone.com

/*** Round half away from zero ('commercial' rounding)* Uses correction to offset floating-point inaccuracies.* Works symmetrically for positive and negative numbers.*/public static double round(double num, int digits) {
// epsilon correctiondouble n = Double.longBitsToDouble(Double.doubleToLongBits(num) + 1);double p = Math.pow(10, digits);return Math.round(n * p) / p;}
// test rounding of halfSystem.out.println(round(0.5, 0));   // 1System.out.println(round(-0.5, 0));  // -1
// testing edge casesSystem.out.println(round(1.005, 2));   // 1.01System.out.println(round(2.175, 2));   // 2.18System.out.println(round(5.015, 2));   // 5.02
System.out.println(round(-1.005, 2));  // -1.01System.out.println(round(-2.175, 2));  // -2.18System.out.println(round(-5.015, 2));  // -5.02

为了实现这一点,我们可以使用这个格式化程序:

 DecimalFormat df = new DecimalFormat("#.00");String resultado = df.format(valor)

或:

DecimalFormat df = new DecimalFormat("0.00"); :

使用此方法始终获取两个小数:

   private static String getTwoDecimals(double value){DecimalFormat df = new DecimalFormat("0.00");return df.format(value);}

定义此值:

91.325.2211.51.22.6

使用该方法,我们可以得到以下结果:

91.325.2211.501.202.60

在线演示。

以下是我的回答:

double num = 4.898979485566356;DecimalFormat df = new DecimalFormat("#.##");time = Double.valueOf(df.format(num));
System.out.println(num); // 4.89

所以在阅读了大部分答案后,我意识到它们中的大多数都不会精确,事实上使用BigDecimal似乎是最好的选择,但是如果你不了解RoundingMode的工作原理,你将不可避免地失去精度。我在一个项目中使用大数时发现了这一点,并认为它可以帮助其他难以舍入数字的人。例如。

BigDecimal bd = new BigDecimal("1363.2749");bd = bd.setScale(2, RoundingMode.HALF_UP);System.out.println(bd.doubleValue());

你会期望得到1363.28作为输出,但你最终会得到1363.27,这是不期望的,如果你不知道RoundingMode在做什么。所以查看oracledocs,你会发现RoundingMode.HALF_UP的以下描述。

舍入模式向“最近邻”舍入,除非两者邻居是等距的,在这种情况下四舍五入。

所以知道了这一点,我们意识到我们不会得到一个精确的四舍五入,除非我们想四舍五入到最近邻。所以,为了完成一个足够的循环,我们需要从n-1小数循环到所需的小数数字。例如。

private double round(double value, int places) throws IllegalArgumentException {
if (places < 0) throw new IllegalArgumentException();
// Cast the number to a String and then separate the decimals.String stringValue = Double.toString(value);String decimals = stringValue.split("\\.")[1];
// Round all the way to the desired number.BigDecimal bd = new BigDecimal(stringValue);for (int i = decimals.length()-1; i >= places; i--) {bd = bd.setScale(i, RoundingMode.HALF_UP);}
return bd.doubleValue();}

这将最终为我们提供预期的输出,即1363.28

我在java 8中使用过贝洛。它对我有用

    double amount = 1000.431;NumberFormat formatter = new DecimalFormat("##.00");String output = formatter.format(amount);System.out.println("output = " + output);

输出:

output = 1000.43

如果需要,可以使用以下方法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)

  1. 为了让尾随的0上升到第5位
DecimalFormat decimalFormatter = new DecimalFormat("#.00000");decimalFormatter.format(0.350500); // result 0.350500
  1. 为了避免0落后到第5位
DecimalFormat decimalFormatter= new DecimalFormat("#.#####");decimalFormatter.format(0.350500); // result o.3505

一个简单的方法来比较,如果它是有限的小数位数。而不是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;}
public static double formatDecimal(double amount) {BigDecimal amt = new BigDecimal(amount);amt = amt.divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_EVEN);return amt.doubleValue();}

使用JUnit测试

@RunWith(Parameterized.class)public class DecimalValueParameterizedTest {
@Parameterized.Parameterpublic double amount;
@Parameterized.Parameter(1)public double expectedValue;
@Parameterized.Parameterspublic static List<Object[]> dataSets() {return Arrays.asList(new Object[][]\{\{1000.0, 1000.0},{1000, 1000.0},{1000.00000, 1000.0},{1000.01, 1000.01},{1000.1, 1000.10},{1000.001, 1000.0},{1000.005, 1000.0},{1000.007, 1000.01},{1000.999, 1001.0},{1000.111, 1000.11}});}
@Testpublic void testDecimalFormat() {Assert.assertEquals(expectedValue, formatDecimal(amount), 0.00);}

非常简单的方法

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

当尝试将小数位数舍入为负数时,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.0100 rounded to -2 dp = 100.01000 rounded to -3 dp = 1000.010000 rounded to -4 dp = 10000.0100000 rounded to -5 dp = 99999.999999999991000000 rounded to -6 dp = 1000000.010000000 rounded to -7 dp = 1.0E7100000000 rounded to -8 dp = 1.0E81000000000 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方法的另一个原因。

这是我发现的只显示小数点后两位的最简单方法。

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