2011-01-25 60 views
33

我有一个double值= 1.068879335我想用1.07这样的两个十进制数来取整。在Java中取整的价值

我试过这样

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) 

可以有一个人告诉我什么是错我的代码。

finaly我需要的最终值= 1.07;

+1

如果这一轮了,1.085879335,2位精度将是如果下降,则为1.09和1.08。你为什么想从1.085879335中获得1.07? – fmucar 2011-01-25 17:38:35

回答

75

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

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

+2

+1用于实际识别问题。您还可以明确告诉DecimalFormat使用C语言环境。 – DJClayworth 2011-01-25 18:00:22

+0

正如我在答案中指出的那样,这种算法通常不起作用。只要Java坚持IEEE浮点,这样的算法就不存在了。 – Waldheinz 2011-01-25 21:26:10

+0

@Waldheinz鉴于问题的背景,我的回答是正确的。公平对待你的想法更进一步,但我应该知道downvote你的答案,因为你完全没有确定为什么代码失败的第一位?当然,我不应该。 – biziclop 2011-01-25 21:36:41

1

你可以尝试定义一个新的DecimalFormat和使用它作为一个double结果到一个新的双变量。

给出的例子让你明白我刚才所说的。

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

这是不可能的所需要的方式,因为有两位小数的数字不能用IEEE浮点数精确表示(for示例1/10 = 0.1不能表示为DoubleFloat)。在将结果呈现给用户之前,格式化应始终发生在最后一步。

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

6

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

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

也有一些是根本性的错误你想要做什么。二进制浮点值不是有小数位数。由于大多数“圆”十进制值不能将其表示为二进制小数,因此无法将一个小数位舍入到给定的小数位数。这就是为什么一个人不应该使用floatdouble代表金钱。

所以,如果你想在你的结果小数位,这一结果必须是一个String(你已拥有的DecimalFormat),或BigDecimal(其中有一个setScale()方法不正是你想要的)。否则,结果不能成为你想要的结果。

阅读The Floating-Point Guide了解更多信息。

18

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 

编辑:正如谢尔盖指出,应该有复接没什么区别双* int和double *双和双分频/ int和double /双。我找不到结果不同的例子。但是,在x86/x64和其他系统上,我认为JVM使用混合double,int值的特定机器代码指令。

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 
1
double TotalPrice=90.98989898898; 

    DecimalFormat format_2Places = new DecimalFormat("0.00"); 

    TotalPrice = Double.valueOf(format_2Places.format(TotalPrice)); 
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; 
    } 
} 
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

阿帕奇共享数学库主页是: http://commons.apache.org/proper/commons-math/index.html

这个方法的内部implemetation是:

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