1395

我想要的是一种将双精度数转换为使用半数方法四舍五入的字符串的方法 - 即,如果要四舍五入的小数是 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 中实现这一目标的最佳方法是什么?

4

37 回答 37

843

使用setRoundingModeRoundingMode明确设置半偶数轮来处理您的问题,然后将格式模式用于所需的输出。

例子:

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

给出输出:

12
123.1235
0.23
0.1
2341234.2125

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

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

要向下舍入,请减去准确度。

于 2008-09-30T16:14:15.940 回答
506

假设valuedouble,你可以这样做:

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

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

于 2008-09-30T16:07:24.550 回答
203
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);

会给你一个BigDecimal。要从中取出字符串,只需调用 thatBigDecimaltoString方法,或者toPlainString为纯格式字符串调用 Java 5+ 的方法。

示例程序:

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));
    }
于 2008-09-30T18:33:56.337 回答
125

您还可以使用

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

以确保您有尾随的 0。

于 2008-09-30T16:58:12.433 回答
92

正如其他一些人所指出的,正确的答案是使用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

编辑:BigDecimal为了解决下面的一些评论,我使用和为模数操作重新定义了测试循环的模数部分,new 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
于 2012-10-02T03:18:23.370 回答
88

假设你有

double d = 9232.129394d;

您可以使用BigDecimal

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

或没有 BigDecimal

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

两种解决方案d == 9232.13

于 2011-01-28T09:52:24.187 回答
64

您可以使用 DecimalFormat 类。

double d = 3.76628729;

DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal =  Double.valueOf(newFormat.format(d));
于 2011-09-29T07:01:59.260 回答
46

Real 的 Java How-to发布了这个解决方案,它也兼容 Java 1.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();
于 2009-09-01T11:14:32.770 回答
32
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
于 2008-09-30T16:09:26.840 回答
31

@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 的美妙之处在于它同时处理字符串的外观——以及设置的舍入精度级别。尔格:以一个代码实现的价格,您可以获得两个好处。;)

于 2011-07-03T15:50:51.653 回答
20

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

  1. DecimalFormat#setRoundingMode()

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

如果您愿意,这里是您可以使用哪些库的建议double。不过,我不建议将它用于字符串转换,因为 double 可能无法准确表示您想要的内容(参见例如此处):

  1. 来自 Apache Commons Math 的精度

    double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
    
  2. Colt 的函数

    double rounded = Functions.round(0.00001).apply(0.912385)
    
  3. 来自 Weka 的实用程序

    double rounded = Utils.roundDouble(0.912385, 5)
    
于 2015-08-15T15:09:34.647 回答
19

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

public static double round(double valueToRound, int numberOfDecimalPlaces)
{
    double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
    double interestedInZeroDPs = valueToRound * multipicationFactor;
    return Math.round(interestedInZeroDPs) / multipicationFactor;
}
于 2011-04-27T15:56:25.130 回答
16

一个简洁的解决方案:

   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提供此功能。

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

于 2017-07-27T13:36:33.137 回答
9

您可以使用 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/

于 2014-07-22T09:49:35.497 回答
8

如果您确实需要十进制数进行计算(而不仅仅是输出),请不要使用基于二进制的浮点格式,如 double。

Use BigDecimal or any other decimal-based format.

我确实使用 BigDecimal 进行计算,但请记住它取决于您正在处理的数字的大小。在我的大多数实现中,我发现从 double 或 integer 解析到 Long 足以进行非常大的数字计算。

事实上,我最近使用 parsed-to-Long 在 GUI 中为 ################## 的数字获得准确的表示(而不是十六进制结果) ############### 个字符(例如)。

于 2011-07-04T09:10:41.860 回答
8

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

 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.32
5.22
11.5
1.2
2.6

使用方法我们可以得到这样的结果:

91.32
5.22
11.50
1.20
2.60

在线演示。

于 2018-03-14T17:40:39.697 回答
7

试试这个:org.apache.commons.math3.util.Precision.round(double x, int scale)

请参阅: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;
        }
    }
}
于 2014-02-20T05:04:07.780 回答
7

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

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

用法很简单

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

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.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double 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 notation
    private 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), "");
    }

}
于 2016-11-10T07:50:39.900 回答
6

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

请先阅读下面的更新

但是,如果您确实想对双精度值进行四舍五入并获得double值结果,则可以org.apache.commons.math3.util.Precision.round(..)如上所述使用。实现使用BigDecimal, 很慢并且会产生垃圾。

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

 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.667
 0.666
 1000.0
 9.00800700601E10

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

披露:我参与了 decimal4j 项目。

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

笔记:

  • 此行为与构造函数的行为非常相似BigDecimal(double)(但与valueOf(double)使用字符串构造函数的行为不同)。
  • 这个问题可以先通过双舍入到更高的精度来规避,但它很复杂,我在这里不再赘述

由于这些原因以及本文上面提到的所有内容,我不建议使用 DoubleRounder

于 2015-11-05T12:54:46.600 回答
5

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

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

}

返回 String 具有所需输出的 ​​a。

于 2016-03-03T11:43:00.023 回答
4

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

如何在 Java 中对数字进行四舍五入

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

Math.round(3.7) // 4

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

圆形的

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

Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4

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

细胞

任何十进制值都会向上舍入到下一个整数。它达到了天花板。此方法返回一个double.

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

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

地面

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

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

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

林特

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

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

Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***
于 2017-02-20T14:42:47.630 回答
4

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

double scale = 100000;    
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;
于 2018-01-07T07:10:46.997 回答
4

这是一个更好的函数,可以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 correction
    double n = Double.longBitsToDouble(Double.doubleToLongBits(num) + 1);
    double p = Math.pow(10, digits);
    return Math.round(n * p) / p;
}

// test rounding of half
System.out.println(round(0.5, 0));   // 1
System.out.println(round(-0.5, 0));  // -1

// testing edge cases
System.out.println(round(1.005, 2));   // 1.01
System.out.println(round(2.175, 2));   // 2.18
System.out.println(round(5.015, 2));   // 5.02

System.out.println(round(-1.005, 2));  // -1.01
System.out.println(round(-2.175, 2));  // -2.18
System.out.println(round(-5.015, 2));  // -5.02
于 2018-02-13T10:37:22.710 回答
4

因此,在阅读了大部分答案后,我意识到大多数答案都不精确,实际上使用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做什么,你最终会得到 ,这是不期望的。因此,查看Oracle 文档,您会发现以下描述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.

于 2019-10-25T20:07:49.337 回答
3

下面的代码片段显示了如何显示 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();
于 2011-09-08T11:09:10.377 回答
3

如果您使用DecimalFormatto 转换doubleString,则非常简单:

DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);

double num = 1.234567;
return formatter.format(num);

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

于 2015-06-28T11:54:36.843 回答
3

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。

于 2016-11-25T09:06:39.857 回答
3

这是我的答案:

double num = 4.898979485566356;
DecimalFormat df = new DecimalFormat("#.##");      
time = Double.valueOf(df.format(num));

System.out.println(num); // 4.89
于 2019-08-21T03:29:57.577 回答
3

我在 java 8 中使用了波纹管。它对我有用

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

输出:

output = 1000.43
于 2020-05-09T04:49:42.287 回答
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)

于 2020-06-24T13:01:32.067 回答
1
  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
于 2020-08-27T01:04:09.080 回答
1
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.Parameter
  public double amount;

  @Parameterized.Parameter(1)
  public double expectedValue;

@Parameterized.Parameters
public 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}
    });
}

@Test
public void testDecimalFormat() {
    Assert.assertEquals(expectedValue, formatDecimal(amount), 0.00);
}
于 2021-01-19T06:53:33.727 回答
0

其中dp = 您想要的小数位,并且value是 double。

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

    double result = Math.round(value * p)/p;
于 2014-04-21T23:51:17.513 回答
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 -如何正确将双精度转换为字符串

于 2016-11-10T22:24:26.357 回答
0

一个简单的方法来比较它是否是有限的小数位数。我们可以使用 Casting,而不是 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;
}
于 2020-10-17T10:24:46.503 回答
0

非常简单的方法

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

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

}

String a = round(12.36545, 2);
于 2021-09-04T15:56:36.157 回答
-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.0 1
这可以通过循环和递归函数来解决。

于 2016-11-22T07:36:21.243 回答