Java中的双值取整

Java中的双值取整,java,double,rounding,numberformatexception,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

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

您可以尝试定义一个新的DecimalFormat,并将其用作新的双精度变量的双精度结果

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

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

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

注意:如前所述,只有在不需要精确控制精度的情况下才应使用浮点。(财务计算是不使用它们的主要例子。)

这在要求的方式中是不可能的,因为有两个小数位的数字不能用IEEE浮点数精确表示(例如1/10=0.1不能表示为
双精度
浮点
). 格式化应始终作为向用户显示结果之前的最后一步进行


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

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

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

你试图做的事情有一些根本性的错误。二进制浮点值没有小数位数。您不能有意义地将一舍入到给定的小数位数,因为大多数“舍入”的十进制值不能表示为二进制分数。这就是为什么人们不应该使用
float
double
来表示货币

因此,如果要在结果中使用小数位数,则该结果必须是
字符串
(使用
DecimalFormat
)或
BigDecimal
(它有一个
setScale()
方法,可以完全满足您的需要)。否则,结果不可能是您想要的结果


阅读了解更多信息。

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
编辑:正如Sergey指出的,将double*int和double*double相乘与将double/int和double/double相除应该没有区别。我找不到一个结果不同的例子。然而,在x86/x64和其他系统上,有一个特定的机器代码指令用于混合双精度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);
}
您可以使用如下格式:

试试这个: org.apache.commons.math3.util.Precision.round(双x,整数刻度)

见:

Apache Commons数学库主页为:

该方法的内部实现为:

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

如果您不想使用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;
}
公共静态双舍入数字(双值,整数数字计数){
如果(数字计数<0)
抛出新的IllegalArgumentException(“四舍五入时数字计数必须为正!”);
双因子=数学功率(10,数字计数);
返回(双精度)(数学四舍五入(值*因子))/因子;
}

如果将此项向上取整,则精度为1.085879335,2位数,如果向下取整,则精度为1.09和1.08。你为什么想从1.085879335中得到1.07?很好,如果这真的是一个货币计算,那么浮点是完全错误的数据类型。你能解释一下examle吗?为什么不能将1/10表示为0.10呢?1/10是0.10,但浮点是二进制的,没有1/10或0.1。只有1/2、1/4、1/8等,并且这些的任意组合都近似为0。1@Manidip对不起,我是AFK,所以我不能及时回答这个问题。但是善良的彼得跳了进来。:-)啊,好吧,你说的是精确性,我现在明白了。用23.8764367843=>23.8800000002得出这个结果怎么样?我认为字符串处理更好。@Manidip,好吧,你也不可能通过将“23.88”解析为double得到准确的23.88,因为23.88无论如何都不能用二进制表示。如果需要精确表示,应该使用某种任意精度的库。你是对的,但我认为我们讨论的是“文本”和“近似”表示,而不是二进制。沃尔德海因茨和彼得回答了上面的问题。DecimalFormat是一个不错的选择,但如果它不起作用,我会尝试使用字符串roundedStr=String.valueOf(rounded);int dotPoint=roundedStr.indexOf(“.”);return(roundedStr).substring(0,dotPoint<0?roundedStr.length():dotPoint+2);这不是完全正确的,如果roundedStr中小数点右侧只有1位,您可能必须在右侧添加填充0,但您知道我之前的评论是什么。@Manidip,如果需要文本表示,那么这当然是另一回事。但我想,这样就没有必要再解析它了。当然,最终取决于如何使用该值。+1用于实际识别问题。您还可以显式地告诉DecimalFormat使用C语言环境
  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;   
    }
}
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;
        }
    }
}
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;
}