Java 中要向上舍入的双精度值

发布于 2024-10-13 18:39:53 字数 547 浏览 4 评论 0原文

我有一个双精度值 = 1.068879335 我想用两个小数值(例如 1.07)将其四舍五入。

我这样尝试,

DecimalFormat df=new DecimalFormat("0.00");
String formate = df.format(value);
double finalValue = Double.parseDouble(formate) ;

这给了我以下异常,

java.lang.NumberFormatException: For input string: "1,07"
     at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1224)
     at java.lang.Double.parseDouble(Double.java:510)

有人可以告诉我我的代码有什么问题吗?

最后我需要 FinalValue = 1.07;

I have a double value = 1.068879335 i want to round it up with only two decimal values like 1.07.

I tried like this

DecimalFormat df=new DecimalFormat("0.00");
String formate = df.format(value);
double finalValue = Double.parseDouble(formate) ;

this is giving me this following exception

java.lang.NumberFormatException: For input string: "1,07"
     at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1224)
     at java.lang.Double.parseDouble(Double.java:510)

can some one tell me what is wrong with my code.

finaly i need the finalValue = 1.07;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

紫﹏色ふ单纯 2024-10-20 18:39:53

请注意字符串中的逗号:“1,07”。 DecimalFormat 使用特定于区域设置的分隔符字符串,而 Double.parseDouble() 则不使用。由于您碰巧生活在小数点分隔符为“,”的国家/地区,因此您无法解析您的号码。

但是,您可以使用相同的 DecimalFormat 来解析它:

DecimalFormat df=new DecimalFormat("0.00");
String formate = df.format(value); 
double finalValue = (Double)df.parse(formate) ;

但是您确实应该这样做:

double finalValue = Math.round( value * 100.0 ) / 100.0;

注意: 正如已经指出的,您应该只在以下情况下使用浮点:您不需要精确控制准确性。 (财务计算是使用它们的主要例子。)

Note the comma in your string: "1,07". DecimalFormat uses a locale-specific separator string, while Double.parseDouble() does not. As you happen to live in a country where the decimal separator is ",", you can't parse your number back.

However, you can use the same DecimalFormat to parse it back:

DecimalFormat df=new DecimalFormat("0.00");
String formate = df.format(value); 
double finalValue = (Double)df.parse(formate) ;

But you really should do this instead:

double finalValue = Math.round( value * 100.0 ) / 100.0;

Note: As has been pointed out, you should only use floating point if you don't need a precise control over accuracy. (Financial calculations being the main example of when not to use them.)

滥情空心 2024-10-20 18:39:53

实时@Sergey 的解决方案,但使用整数除法。

double value = 23.8764367843;
double rounded = (double) Math.round(value * 100) / 100;
System.out.println(value +" rounded is "+ rounded);

打印

23.8764367843 rounded is 23.88

编辑:正如谢尔盖指出的那样,乘以 double*int 和 double*double 与除以 double/int 和 double/double 之间应该没有区别。我找不到结果不同的例子。然而,在 x86/x64 和其他系统上,有一个针对混合 double,int 值的特定机器代码指令,我相信 JVM 使用它。

for (int j = 0; j < 11; j++) {
    long start = System.nanoTime();
    for (double i = 1; i < 1e6; i *= 1.0000001) {
        double rounded = (double) Math.round(i * 100) / 100;
    }
    long time = System.nanoTime() - start;
    System.out.printf("double,int operations %,d%n", time);
}
for (int j = 0; j < 11; j++) {
    long start = System.nanoTime();
    for (double i = 1; i < 1e6; i *= 1.0000001) {
        double rounded = (double) Math.round(i * 100.0) / 100.0;
    }
    long time = System.nanoTime() - start;
    System.out.printf("double,double operations %,d%n", time);
}

印刷

double,int operations 613,552,212
double,int operations 661,823,569
double,int operations 659,398,960
double,int operations 659,343,506
double,int operations 653,851,816
double,int operations 645,317,212
double,int operations 647,765,219
double,int operations 655,101,137
double,int operations 657,407,715
double,int operations 654,858,858
double,int operations 648,702,279
double,double operations 1,178,561,102
double,double operations 1,187,694,386
double,double operations 1,184,338,024
double,double operations 1,178,556,353
double,double operations 1,176,622,937
double,double operations 1,169,324,313
double,double operations 1,173,162,162
double,double operations 1,169,027,348
double,double operations 1,175,080,353
double,double operations 1,182,830,988
double,double operations 1,185,028,544

Live @Sergey's solution but with integer division.

double value = 23.8764367843;
double rounded = (double) Math.round(value * 100) / 100;
System.out.println(value +" rounded is "+ rounded);

prints

23.8764367843 rounded is 23.88

EDIT: As Sergey points out, there should be no difference between multipling double*int and double*double and dividing double/int and double/double. I can't find an example where the result is different. However on x86/x64 and other systems there is a specific machine code instruction for mixed double,int values which I believe the JVM uses.

for (int j = 0; j < 11; j++) {
    long start = System.nanoTime();
    for (double i = 1; i < 1e6; i *= 1.0000001) {
        double rounded = (double) Math.round(i * 100) / 100;
    }
    long time = System.nanoTime() - start;
    System.out.printf("double,int operations %,d%n", time);
}
for (int j = 0; j < 11; j++) {
    long start = System.nanoTime();
    for (double i = 1; i < 1e6; i *= 1.0000001) {
        double rounded = (double) Math.round(i * 100.0) / 100.0;
    }
    long time = System.nanoTime() - start;
    System.out.printf("double,double operations %,d%n", time);
}

Prints

double,int operations 613,552,212
double,int operations 661,823,569
double,int operations 659,398,960
double,int operations 659,343,506
double,int operations 653,851,816
double,int operations 645,317,212
double,int operations 647,765,219
double,int operations 655,101,137
double,int operations 657,407,715
double,int operations 654,858,858
double,int operations 648,702,279
double,double operations 1,178,561,102
double,double operations 1,187,694,386
double,double operations 1,184,338,024
double,double operations 1,178,556,353
double,double operations 1,176,622,937
double,double operations 1,169,324,313
double,double operations 1,173,162,162
double,double operations 1,169,027,348
double,double operations 1,175,080,353
double,double operations 1,182,830,988
double,double operations 1,185,028,544
魂ガ小子 2024-10-20 18:39:53

问题是您使用本地化格式化程序来生成特定于区域设置的小数点,在您的情况下为“,”。但 Double.parseDouble() 需要非本地化的双文本。您可以通过使用特定于区域设置的解析方法或将格式化程序的区域设置更改为使用“.”的区域来解决您的问题。作为小数点。或者更好的是,通过使用如下内容来避免不必要的格式化:

double rounded = (double) Math.round(value * 100.0) / 100.0;

The problem is that you use a localizing formatter that generates locale-specific decimal point, which is "," in your case. But Double.parseDouble() expects non-localized double literal. You could solve your problem by using a locale-specific parsing method or by changing locale of your formatter to something that uses "." as the decimal point. Or even better, avoid unnecessary formatting by using something like this:

double rounded = (double) Math.round(value * 100.0) / 100.0;
被翻牌 2024-10-20 18:39:53

您尝试做的事情存在根本性错误。二进制浮点值没有小数位。您无法有意义地将 1 舍入到给定的小数位数,因为大多数“舍入”十进制值根本无法表示为二进制分数。这就是为什么永远不要使用 floatdouble 来表示金钱。

因此,如果您希望结果中包含小数位,则该结果必须是 String(您已通过 DecimalFormat 获得)或 BigDecimal > (它有一个 setScale() 方法,可以完全满足您的需求)。否则,结果不可能是你想要的。

请阅读浮点指南了解更多信息。

There is something fundamentally wrong with what you're trying to do. Binary floating-points values do not have decimal places. You cannot meaningfully round one to a given number of decimal places, because most "round" decimal values simply cannot be represented as a binary fraction. Which is why one should never use float or double to represent money.

So if you want decimal places in your result, that result must either be a String (which you already got with the DecimalFormat), or a BigDecimal (which has a setScale() method that does exactly what you want). Otherwise, the result cannot be what you want it to be.

Read The Floating-Point Guide for more information.

╄→承喏 2024-10-20 18:39:53

试试这个:
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;
        }
    }
}

Try this:
org.apache.commons.math3.util.Precision.round(double x, int scale)

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

Apache Commons Mathematics Library homepage is:
http://commons.apache.org/proper/commons-math/index.html

The internal implemetation of this method is:

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;
        }
    }
}
满地尘埃落定 2024-10-20 18:39:53

您可以尝试定义一个新的 DecimalFormat 并将其用作新的 double 变量的 Double 结果。

举个例子让你明白我刚才说的。

double decimalnumber = 100.2397;
DecimalFormat dnf = new DecimalFormat( "#,###,###,##0.00" );
double roundednumber = new Double(dnf.format(decimalnumber)).doubleValue();

You could try defining a new DecimalFormat and using it as a Double result to a new double variable.

Example given to make you understand what I just said.

double decimalnumber = 100.2397;
DecimalFormat dnf = new DecimalFormat( "#,###,###,##0.00" );
double roundednumber = new Double(dnf.format(decimalnumber)).doubleValue();
杯别 2024-10-20 18:39:53

这在请求的方式中是不可能的,因为有两位小数的数字无法使用 IEEE 浮点数精确表示(例如 1/10 = 0.1 不能表示为 Double浮动)。格式化应该始终作为将结果呈现给用户之前的最后一步进行。

我猜你这么问是因为你想处理货币价值。没有办法用浮点数可靠地做到这一点,你应该考虑切换到定点算术。这可能意味着所有计算都以“美分”而不是“美元”为单位。

This is not possible in the requested way because there are numbers with two decimal places which can not be expressed exactly using IEEE floating point numbers (for example 1/10 = 0.1 can not be expressed as a Double or Float). The formatting should always happen as the last step before presenting the result to the user.

I guess you are asking because you want to deal with monetary values. There is no way to do this reliably with floating-point numbers, you shoud consider switching to fixed-point arithmetics. This probably means doing all calculations in "cents" instead of "dollars".

紫罗兰の梦幻 2024-10-20 18:39:53
double TotalPrice=90.98989898898;

  DecimalFormat format_2Places = new DecimalFormat("0.00");

    TotalPrice = Double.valueOf(format_2Places.format(TotalPrice));
double TotalPrice=90.98989898898;

  DecimalFormat format_2Places = new DecimalFormat("0.00");

    TotalPrice = Double.valueOf(format_2Places.format(TotalPrice));
夏花。依旧 2024-10-20 18:39:53

您可以使用类似 的格式在这里,

  public static double getDoubleValue(String value,int digit){
    if(value==null){
        value="0";
     }
    double i=0;
     try {
         DecimalFormat digitformat = new DecimalFormat("#.##");
         digitformat.setMaximumFractionDigits(digit);
        return Double.valueOf(digitformat.format(Double.parseDouble(value)));

    } catch (NumberFormatException numberFormatExp) {
        return i;   
    }
}

You can use format like here,

  public static double getDoubleValue(String value,int digit){
    if(value==null){
        value="0";
     }
    double i=0;
     try {
         DecimalFormat digitformat = new DecimalFormat("#.##");
         digitformat.setMaximumFractionDigits(digit);
        return Double.valueOf(digitformat.format(Double.parseDouble(value)));

    } catch (NumberFormatException numberFormatExp) {
        return i;   
    }
}
白首有我共你 2024-10-20 18:39:53

如果您不想使用 DecimalFormat (例如由于其效率)并且想要一个通用的解决方案,您也可以尝试这种使用缩放舍入的方法:

public static double roundToDigits(double value, int digitCount) {
    if (digitCount < 0)
        throw new IllegalArgumentException("Digit count must be positive for rounding!");

    double factor = Math.pow(10, digitCount);
    return (double)(Math.round(value * factor)) / factor;
}

If you do not want to use DecimalFormat (e.g. due to its efficiency) and you want a general solution, you could also try this method that uses scaled rounding:

public static double roundToDigits(double value, int digitCount) {
    if (digitCount < 0)
        throw new IllegalArgumentException("Digit count must be positive for rounding!");

    double factor = Math.pow(10, digitCount);
    return (double)(Math.round(value * factor)) / factor;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文