如何在Java中把数字转换成小数位数decimal

How to round a number to n decimal places in Java

我想要的是一种将双精度数转换为字符串的方法,该字符串使用半向上方法进行舍入-即,如果要舍入的十进制数为5,则它总是向上舍入到前一个数字。这是大多数人在大多数情况下期望的标准舍入方法。

我也希望只显示有效数字-也就是说,不应该有任何尾随的零。

我知道这样做的一种方法是使用String.format方法:

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

返回:

1
0.91239

很好,但是它总是显示小数点后5位的数字,即使它们不重要:

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

返回:

1
0.91230

另一种方法是使用DecimalFormatter

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

返回:

1
0.91238

但是,正如您所看到的,这使用了半偶数取整。也就是说,如果前一个数字是偶数,它将向下取整。我想要的是:

1
2
0.912385 -> 0.91239
0.912300 -> 0.9123

在Java中实现这个最好的方法是什么?


使用setRoundingMode,将RoundingMode显式设置为用半偶数轮处理问题,然后使用格式模式进行所需的输出。

例子:

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

给出输出:

1
2
3
4
5
12
123.1235
0.23
0.1
2341234.2125


假设valuedouble的话,你可以这样做:

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

精确到5位数。零的数目表示小数的数目。


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

会给你买一辆BigDecimal。为了得到它的字符串,只需调用EDCOX1 4的EDCOX1×6的方法,或者对于纯格式字符串,Java 5 +的EDCOX1 7Ω方法。

样本程序:

1
2
3
4
5
6
7
8
9
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));
    }


您也可以使用

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

以确保后面有0。


假设你有

1
double d = 9232.129394d;

您可以使用BigDecimal

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

或不带BigDecimal

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

使用两种解决方案d == 9232.13


正如其他一些人所指出的,正确的答案是使用DecimalFormatBigDecimal。浮点没有小数点,因此您不可能在第一个位置舍入/截断到它们的特定数字。你必须以十进制为基数,这就是这两个类所做的。

我将把下面的代码作为一个反例发布到这个线程中的所有答案上,甚至在StackOverflow(和其他地方)上,它建议先乘后截断,再除以。这种技术的倡导者有责任解释为什么下面的代码在92%以上的情况下产生错误的输出。

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

本程序输出:

1
10001 trials 9251 errors

编辑:为了解决下面的一些意见,我使用BigDecimalnew MathContext(16)重新计算了模运算的测试循环的模部分,如下所示:

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

结果:

1
10001 trials 4401 errors


您可以使用decimalformat类。

1
2
3
4
double d = 3.76628729;

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


Realm的Java如何发布这个解决方案,它也兼容Java 1.6之前的版本。

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

1
2
3
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;


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

You can also use the

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

to make sure you have the trailing 0's.

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

假设:您必须在GUI中实现舍入机制程序。简单地改变结果输出的精度更改插入符号格式(即括号内)。以便:

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

将作为输出返回:0.912385

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

将作为输出返回:0.91239

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

将作为输出返回:0.9124

[编辑:如果插入符号格式是这样的("0."),那么您输入一个小数,例如3.1415926,作为参数,decimalFormat不产生任何垃圾(例如尾随零),将返回:3.1415926。如果你有这种倾向的话。当然,有点冗长因为喜欢一些dev的-但是嘿,它的内存占用很低在处理过程中,非常容易实现。]

因此,本质上,decimalformat的优点在于它同时处理字符串外观-以及舍入精度集的级别。埃尔戈:你以一个代码实现的价格获得两个好处。;)


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

1
2
3
4
5
6
public static double round(double valueToRound, int numberOfDecimalPlaces)
{
    double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
    double interestedInZeroDPs = valueToRound * multipicationFactor;
    return Math.round(interestedInZeroDPs) / multipicationFactor;
}


这里是一个总结,如果你想你可以使用一个字符串:

  • decimalformat # setroundingmode():

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

    1
    2
    3
    String str2 = new BigDecimal(0.912385)
        .setScale(5, BigDecimal.ROUND_HALF_UP)
        .toString();
  • 这里是一个建议,你可以使用什么库,如果你想doubleas a result。我不会推荐它的字符串转换为双,虽然,可能不可以代表你想要的(例如:这里是湖)

  • 从Apache Commons数学精度

    1
    double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
  • 函数从小马

    1
    double rounded = Functions.round(0.00001).apply(0.912385)
  • 在weka工具

    1
    double rounded = Utils.roundDouble(0.912385, 5)

  • 简洁的解决方案:

    1
    2
    3
    4
       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提供此服务。


    你可以使用BigDecimal

    1
    2
    3
    4
    5
    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 /精密工程学院的小数被使用-被枚举/时尚


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

    1
    Use BigDecimal or any other decimal-based format.

    我确实使用bigdecimal进行计算,但请记住,它取决于你要处理的数字。在我的大多数实现中,我发现从double或整数到长的长度足以进行非常大的数值计算。

    事实上,我已经最近使用的解析为long以获得准确的表示(而不是十六进制结果)在一个图形用户界面中,数字的大小为\\3535353535\3535\\\35\35\35\35\\\35\___字符(作为例子)。


    试试这个:org.apache.commons.math3.util.precision.round(double x,int量表)

    湖:http://commons.apache.org /正确/共享/组织/数学/ apidocs Apache Commons math3 util / / / / precision.html

    Apache Commons数学图书馆主页是:http://commons.apache.org /数学/共享服务。

    内部implemetation本法是:

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

    自从我找到完整的答案没有在这个主题我已经把那本应在一级处理,以支持:

    • 格式:格式字符串和一双的一个十进制数的某些地方
    • 解析:解析格式化值的双回
    • 现场:现场使用默认格式和解析
    • 指数记数法:开始使用指数符号后一定门限

    很简单的用法是:

    (在这个例子的缘故,我使用自定义设置)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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

    这里是类:

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    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),"");
        }

    }

    只是在有人需要帮助,与本案例的安静。这个解决方案,我的作品完美。

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

    }

    返回a String 与所需的输出。


    为此,我们可以使用此格式化程序:

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

    或:

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

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

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

    定义此值:

    1
    2
    3
    4
    5
    91.32
    5.22
    11.5
    1.2
    2.6

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

    1
    2
    3
    4
    5
    91.32
    5.22
    11.50
    1.20
    2.60

    在线演示。


    如果你使用一个转换doubleDecimalFormatString,它非常简单:

    1
    2
    3
    4
    5
    DecimalFormat formatter = new DecimalFormat("0.0##");
    formatter.setRoundingMode(RoundingMode.HALF_UP);

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

    有几个RoundingMode枚举的价值选择和行为,取决于你的需要。


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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();

    我来这里只是想得到一个关于如何取整数字的简单答案。这是一个补充答案。

    如何在Java中循环数字

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

    1
    Math.round(3.7) // 4

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

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

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

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

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

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


    我同意与选定的答案用DecimalFormat-或BigDecimal也。

    请读下面的更新第一!

    但是如果你做想环游double值双值和get a result,你可以使用以上org.apache.commons.math3.util.Precision.round(..)AS。外部使用BigDecimal慢和垃圾,是创建。

    一个类似的,但几乎无法提供和垃圾是由DoubleRounder公用库:在decimal4j></s

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

    想输出

    1
    2
    3
    4
     0.667
     0.666
     1000.0
     9.00800700601E10

    湖http:/ / / / / github.com tools4j decimal4j维基/ doublerounder效用

    免责声明:我decimal4j参与的项目。

    更新:作为替代doublerounder @ iaforek counterintuitive有时返回出结果。原因是,它mathematically被正确执行。例如DoubleRounder.round(256.025d, 2)将被储存到256.02因为双值代表在较小的比为256.025d是理性和价值,因此将256.025储存下来。

    说明:

    • 这种行为是非常类似于《BigDecimal(double)构造函数(这是在不到valueOf(double)使用字符串的构造函数)。
    • 一个问题可以被circumvented双降压到一个高精度的第一,但它是复杂的,我不会进入细节在这里

    对于那些在这一切以上原因后,很doublerounder i无法使用。


    如果您使用的技术具有最小的JDK。这里有一个没有Java LIBS的方法:

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


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

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

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

    如果需要大的小数位数值,可以改用BigDecimal。无论如何,.0是重要的。如果没有它,则舍入0.33333d5返回0.33333,仅允许9位数字。没有.0的第二个函数存在0.30000返回0.30000000000000004的问题。


    记住,string.format)和字符串(默认decimalformat生产现场使用。所以他们可以写一点格式化数或逗号作为十进制整数和分离器之间的配件。这是为了确保储存格式字符串中使用java.text.numberformat:你想要的那样

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      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.99y=8.8608x~2-110.8516x+330.6251.123.00

    的例子是从farenda如何采取正确的字符串转换为双。


    如果你考虑N 5或十进制数。解决这个问题可能是你的答案。

    1
    2
    3
    4
    5
    6
        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输出>本可以解决与循环和递归函数。


    一般来说,舍入是通过缩放来完成的:round(num / p) * p

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    /**
     * MidpointRounding away from zero ('arithmetic' rounding)
     * Uses a half-epsilon for correction. (This offsets IEEE-754
     * half-to-even rounding that was applied at the edge cases).
     */

    double RoundCorrect(double num, int precision) {
        double c = 0.5 * EPSILON * num;
    //  double p = Math.pow(10, precision); //slow
        double p = 1; while (precision--> 0) p *= 10;
        if (num < 0)
            p *= -1;
        return Math.round((num + c) * p) / p;
    }

    // testing edge cases
    RoundCorrect(1.005, 2);   // 1.01 correct
    RoundCorrect(2.175, 2);   // 2.18 correct
    RoundCorrect(5.015, 2);   // 5.02 correct

    RoundCorrect(-1.005, 2);  // -1.01 correct
    RoundCorrect(-2.175, 2);  // -2.18 correct
    RoundCorrect(-5.015, 2);  // -5.02 correct


    在DP =十进制的地方你想要的。价值是一个双。

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

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