将一个小数加倍到2位小数

Raj*_*esh 447 java double rounding

如果值为200.3456,则应格式化为200.34.如果是200,那应该是200.00.

Jon*_*nik 760

下面是一个实用(而不是截断)双到小数位的指定数量.

例如:

round(200.3456, 2); // returns 200.35
Run Code Online (Sandbox Code Playgroud)

原始版本; 小心这个

public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    long factor = (long) Math.pow(10, places);
    value = value * factor;
    long tmp = Math.round(value);
    return (double) tmp / factor;
}
Run Code Online (Sandbox Code Playgroud)

这在具有非常高的小数位数(例如)或大整数部分(例如)的极端情况下严重崩溃.感谢Sloin指出这一点.round(1000.0d, 17)round(90080070060.1d, 9)

我一直在使用上面的方法将"不太大"的双打多次绕到2或3个小数位(例如,为了记录目的,以秒为单位清理时间:27.987654321987 - > 27.99).但我想最好避免它,因为更可靠的方法随时可用,代码也更清晰.

所以,请改用它

(改编自Louis Wasserman的这个答案肖恩欧文的这个答案.)

public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    BigDecimal bd = BigDecimal.valueOf(value);
    bd = bd.setScale(places, RoundingMode.HALF_UP);
    return bd.doubleValue();
}
Run Code Online (Sandbox Code Playgroud)

请注意,这HALF_UP是"通常在学校教授"的舍入模式.细读的RoundingMode文件,如果你怀疑你需要别的东西,如银行家舍入.

当然,如果您愿意,可以将上述内容简化为单行:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()

并且在每种情况下

永远记住,浮点表示使用floatdouble不准确的.例如,考虑以下表达式:

999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001
Run Code Online (Sandbox Code Playgroud)

为了准确,您想要使用BigDecimal.在它的时候,使用带有String的构造函数,而不是使用double的构造函数.例如,尝试执行此操作:

System.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));
Run Code Online (Sandbox Code Playgroud)

关于该主题的一些优秀的进一步阅读


如果您想要字符串格式而不是(或除此之外)严格舍入数字,请参阅其他答案.

具体来说,请注意round(200, 0)返回200.0.如果你想输出" 200.00 ",你应该首先进行舍入然后格式化输出的结果(这在Jesper的答案中得到了很好的解释).

  • 再一次,downvotes对评论更有用.(请注意,问题*是不明确的,我的回答清楚地表明它并没有解决问题的每一种解释.) (30认同)
  • @lisak:在什么情况下舍入到18位有意义?*舍入*不是创建简化表示的要点吗?好吧,也许在计算大笔贷款的利息时..但希望任何进行财务计算的人都知道使用`BigDecimal`代替`double`来表示他们的价值,所以不会寻找这个解决方案.滥用方法,然后称之为"shitty",是不专业的.然而,突出解决方案的局限性是很好的. (3认同)
  • 阅读关于该答案的第一条评论.显然,如果你正在处理精确(例如货币)价值,你[应该**首先不要使用双倍](http://stackoverflow.com/questions/3730019/why-not-use-双或-float到表示币种).(在这种情况下,[使用BigDecimal](http://stackoverflow.com/questions/285680/representing-monetary-values-in-java).) (2认同)
  • 谢谢,这看起来很坚如磐石,但是这两种衬里更加优雅:返回新的BigDecimal(value).setScale(places,BigDecimal.ROUND_HALF_UP).doubleValue(); (2认同)

Jes*_*per 317

如果您只想double在小数点后打印两位数,请使用以下内容:

double value = 200.3456;
System.out.printf("Value: %.2f", value);
Run Code Online (Sandbox Code Playgroud)

如果要将结果放在a String而不是打印到控制台,请使用String.format()相同的参数:

String result = String.format("%.2f", value);
Run Code Online (Sandbox Code Playgroud)

或者使用课程DecimalFormat:

DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));
Run Code Online (Sandbox Code Playgroud)

  • 使用`DecimalFormat`,您还可以选择舍入模式; default将与OP的示例匹配,或者他们可能需要`RoundingMode.DOWN`. (4认同)
  • 这个答案是*真正的答案......其他人围绕双人,这是一个完全不同的格式化操作. (2认同)

小智 121

我认为这更容易:

double time = 200.3456;
DecimalFormat df = new DecimalFormat("#.##");      
time = Double.valueOf(df.format(time));

System.out.println(time); // 200.35
Run Code Online (Sandbox Code Playgroud)

请注意,这实际上会为您进行舍入,而不仅仅是格式化.

  • 请注意,如果用户区域设置不是US-en或类似的,则会中断.例如,在西班牙语中,格式为"#,##".请改用Jonik的答案. (15认同)

luk*_*uke 69

最简单的方法就是做这样的伎俩;

double val = ....;
val = val*100;
val = Math.round(val);
val = val /100;
Run Code Online (Sandbox Code Playgroud)

如果val从200.3456开始然后转到20034.56那么它将四舍五入到20035然后我们将它除以得到200.34.

如果你想要总是向下舍入,我们总是可以通过强制转换为int来截断:

double val = ....;
val = val*100;
val = (double)((int) val);
val = val /100;
Run Code Online (Sandbox Code Playgroud)

这种技术适用于大多数情况,因为对于非常大的双精度(正或负),它可能会溢出.但如果您知道您的价值观将在适当的范围内,那么这应该适合您.

  • 好简单的答案。我只补充说`Math.Round`应该是`Math.round`。而且,`Math.Round(val);`的结果应该转换为double,因为它通常会返回一个long:`val =(double)Math.round(val);` (2认同)

Pri*_*tre 48

请使用Apache commons math:

Precision.round(10.4567, 2)
Run Code Online (Sandbox Code Playgroud)

  • @EJP你为什么这么挑剔?所有人要做的就是将返回值赋给变量...... (23认同)
  • 请注意,在内部,[Precision.round](http://commons.apache.org/proper/commons-math/javadocs/api-3.3/src-html/org/apache/commons/math3/util/Precision.html# line.395) 只是将 Double 转换为 BigDecimal,然后再转换回来,就像 Jonik 的解决方案一样。 (4认同)
  • 我认为这是一个非常干净的解决方案,即使它让你依赖于一个库. (3认同)

小智 36

function Double round2(Double val) {
    return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}
Run Code Online (Sandbox Code Playgroud)

注意toString()!!!!

这是因为BigDecimal转换双精确二进制形式!

这些是各种建议的方法及其失败案例.

// Always Good!
new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue() 

Double val = 260.775d; //EXPECTED 260.78
260.77 - WRONG - new BigDecimal(val).setScale(2,RoundingMode.HALF_UP).doubleValue()

Double val = 260.775d; //EXPECTED 260.78
260.77 - TRY AGAIN - Math.round(val * 100.d) / 100.0d  

Double val = 256.025d; //EXPECTED 256.03d
256.02 - OOPS - new DecimalFormat("0.00").format(val) 
// By default use half even, works if you change mode to half_up 

Double val = 256.025d; //EXPECTED 256.03d
256.02 - FAIL - (int)(val * 100 + 0.5) / 100.0;
Run Code Online (Sandbox Code Playgroud)

  • 应该是接受的答案,因为与您清晰可读的答案相比,被接受的答案是如此混乱 (5认同)

Abd*_*zmy 27

double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");      
System.out.println(df.format(value));
Run Code Online (Sandbox Code Playgroud)


小智 16

double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);
Run Code Online (Sandbox Code Playgroud)


dao*_*way 14

如果你真的想要相同的double,但是你想要的方式可以使用BigDecimal,例如

new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
Run Code Online (Sandbox Code Playgroud)


Ign*_*ams 9

四舍五入通常不是人们想要的.相反,用String.format()它来表示所需的格式.

  • 我需要四舍五入以将其用作进一步计算中的粒度级别 (2认同)

Sru*_*lla 8

对于两个舍入数字.非常简单,你基本上更新变量而不仅仅是DecimalFormat所做的显示目的.

x = Math.floor(x * 100) / 100;