在Java中向上舍入的双重值

时间:2011-01-25 17:23:30

标签: java double rounding numberformatexception

我有一个双精度值= 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;

10 个答案:

答案 0 :(得分:76)

请注意字符串中的逗号:“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;

注意:正如已经指出的那样,如果您不需要精确控制精度,则应该只使用浮点数。 (财务计算是使用它们时的主要例子。)

答案 1 :(得分:19)

Live @ 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

答案 2 :(得分:7)

问题是您使用的是本地化格式化程序,它会生成特定于区域设置的小数点,在您的情况下为“,”。但是Double.parseDouble()需要非本地化的双字面值。您可以通过使用特定于语言环境的解析方法或将格式化程序的语言环境更改为使用“。”的方法来解决您的问题。作为小数点。或者甚至更好,通过使用类似的东西避免不必要的格式化:

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

答案 3 :(得分:4)

你要做的事情有根本性的错误。二进制浮点值不具有小数位。你不能有意义地将一个舍入到给定的小数位数,因为大多数“圆”小数值根本不能表示为二进制小数。这就是为什么不应该使用floatdouble代表金钱。

因此,如果您想在结果中使用小数位,那么结果必须是String(您已使用DecimalFormat获得的)或BigDecimal(具有{ {1}}完全符合您要求的方法。否则,结果可能不是您想要的结果。

阅读The Floating-Point Guide了解详情。

答案 4 :(得分:2)

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

答案 5 :(得分:1)

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

让你理解我刚才所说的例子。

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

答案 6 :(得分:1)

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

我想你是在问,因为你想要处理货币价值。使用浮点数无法可靠地执行此操作,您应该考虑切换到定点算术。这可能意味着以“美分”而不是“美元”进行所有计算。

答案 7 :(得分:1)

double TotalPrice=90.98989898898;

  DecimalFormat format_2Places = new DecimalFormat("0.00");

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

答案 8 :(得分:0)

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

答案 9 :(得分:0)

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

uid