这个问题在这里已有答案:
如果值为 200.3456 ,则应将其格式化为 200.34 . 如果它是 200 ,那么它应该是 200.00 .
200.3456
200.34
200
200.00
这是一个实用程序 rounds (而不是截断)一个double到指定的小数位数 .
例如:
round(200.3456, 2); // returns 200.35
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; }
这个 breaks down badly 在极端情况下具有非常多的小数位(例如 round(1000.0d, 17) )或大整数部分(例如 round(90080070060.1d, 9) ) . 感谢Sloin指出这一点 .
round(1000.0d, 17)
round(90080070060.1d, 9)
我一直在使用上面的内容将“不太大”的双打多次圆满到2或3个小数位(例如为了记录目的,以秒为单位清理时间:27.987654321987 - > 27.99) . 但我想最好避免使用它,因为更可靠的方法随时可用,代码也更清晰 .
(改编自this answer by Louis Wasserman和this one by Sean Owen . )
public static double round(double value, int places) { if (places < 0) throw new IllegalArgumentException(); BigDecimal bd = new BigDecimal(value); bd = bd.setScale(places, RoundingMode.HALF_UP); return bd.doubleValue(); }
请注意 HALF_UP 是舍入模式"commonly taught at school" . 仔细阅读RoundingMode documentation,如果您怀疑需要其他东西,例如Bankers’ Rounding .
HALF_UP
当然,如果您愿意,可以将上述内容整理成一行:new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()
永远记住使用 float 和 double 的浮点表示是不精确的 . 例如,考虑以下表达式:
float
double
999199.1231231235 == 999199.1231231236 // true 1.03 - 0.41 // 0.6200000000000001
For exactness, you want to use 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")));
关于该主题的一些优秀的进一步阅读
第48项:“如果需要确切的答案,请避免使用 float 和 double ”在Joshua Bloch的Effective Java(第2版)中
What Every Programmer Should Know About Floating-Point Arithmetic
如果您想要字符串格式而不是(或除此之外)严格舍入数字,请参阅其他答案 .
具体来说,请注意 round(200, 0) 返回 200.0 . 如果要输出“ 200.00 ”,首先应该舍入然后格式化输出结果(这在Jesper's answer中有完整的解释) .
round(200, 0)
200.0
如果您只想打印小数点后两位数的 double ,请使用以下内容:
double value = 200.3456; System.out.printf("Value: %.2f", value);
如果要将结果放在 String 而不是打印到控制台,请使用带有相同参数的 String.format() :
String
String.format()
String result = String.format("%.2f", value);
或者使用类 DecimalFormat :
DecimalFormat
DecimalFormat df = new DecimalFormat("####0.00"); System.out.println("Value: " + df.format(value));
我认为这更容易:
double time = 200.3456; DecimalFormat df = new DecimalFormat("#.##"); time = Double.valueOf(df.format(time)); System.out.println(time); // 200.35
请注意,这实际上会为您进行舍入,而不仅仅是格式化 .
最简单的方法就是做这样的伎俩;
double val = ....; val = val*100; val = Math.round(val); val = val /100;
如果val从200.3456开始然后转到20034.56那么它将四舍五入到20035然后我们将它除以得到200.34 .
如果你想要总是向下舍入,我们总是可以通过强制转换为int来截断:
double val = ....; val = val*100; val = (double)((int) val); val = val /100;
这种技术适用于大多数情况,因为对于非常大的双精度(正或负),它可能会溢出 . 但如果您知道您的 Value 观将在适当的范围内,那么这应该适合您 .
请使用Apache commons math:
Precision.round(10.4567, 2)
function Double round2(Double val) { return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue(); }
注意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;
double value= 200.3456; DecimalFormat df = new DecimalFormat("0.00"); System.out.println(df.format(value));
double d = 28786.079999999998; String str = String.format("%1.2f", d); d = Double.valueOf(str);
如果你真的想要相同的double,但是以你想要的方式舍入,你可以使用BigDecimal
new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
四舍五入通常不是人们想要的 . 而是使用String.format()以所需格式表示它 .
对于两个舍入数字 . 非常简单,您基本上更新变量而不仅仅是DecimalFormat所做的显示目的 .
x = Math.floor(x * 100) / 100;
value = (int)(value * 100 + 0.5) / 100.0;
在你的问题中,似乎你想避免舍入数字?我认为.format()将使用half-up,afaik对数字进行舍入?因此,如果你想要舍入,200.3456应该是200.35,精度为2.但在你的情况下,如果你只想要前2然后丢弃其余的?
您可以将它乘以100,然后转换为int(或取数字的最低点),然后再将其除以100 .
200.3456 * 100 = 20034.56; (int) 20034.56 = 20034; 20034/100.0 = 200.34;
你可能会遇到与边界接近的真正大数字的问题 . 在这种情况下,转换为字符串和子字符串,它将同样容易 .
13 回答
这是一个实用程序 rounds (而不是截断)一个double到指定的小数位数 .
例如:
原始版本;小心这一点
这个 breaks down badly 在极端情况下具有非常多的小数位(例如
round(1000.0d, 17)
)或大整数部分(例如round(90080070060.1d, 9)
) . 感谢Sloin指出这一点 .我一直在使用上面的内容将“不太大”的双打多次圆满到2或3个小数位(例如为了记录目的,以秒为单位清理时间:27.987654321987 - > 27.99) . 但我想最好避免使用它,因为更可靠的方法随时可用,代码也更清晰 .
所以,请改用它
(改编自this answer by Louis Wasserman和this one by Sean Owen . )
请注意
HALF_UP
是舍入模式"commonly taught at school" . 仔细阅读RoundingMode documentation,如果您怀疑需要其他东西,例如Bankers’ Rounding .当然,如果您愿意,可以将上述内容整理成一行:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()
并且在每种情况下
永远记住使用
float
和double
的浮点表示是不精确的 . 例如,考虑以下表达式:For exactness, you want to use BigDecimal . 在它的时候,使用带有String的构造函数,而不是使用double的构造函数 . 例如,尝试执行此操作:
关于该主题的一些优秀的进一步阅读
第48项:“如果需要确切的答案,请避免使用
float
和double
”在Joshua Bloch的Effective Java(第2版)中What Every Programmer Should Know About Floating-Point Arithmetic
如果您想要字符串格式而不是(或除此之外)严格舍入数字,请参阅其他答案 .
具体来说,请注意
round(200, 0)
返回200.0
. 如果要输出“ 200.00 ”,首先应该舍入然后格式化输出结果(这在Jesper's answer中有完整的解释) .如果您只想打印小数点后两位数的
double
,请使用以下内容:如果要将结果放在
String
而不是打印到控制台,请使用带有相同参数的String.format()
:或者使用类
DecimalFormat
:我认为这更容易:
请注意,这实际上会为您进行舍入,而不仅仅是格式化 .
最简单的方法就是做这样的伎俩;
如果val从200.3456开始然后转到20034.56那么它将四舍五入到20035然后我们将它除以得到200.34 .
如果你想要总是向下舍入,我们总是可以通过强制转换为int来截断:
这种技术适用于大多数情况,因为对于非常大的双精度(正或负),它可能会溢出 . 但如果您知道您的 Value 观将在适当的范围内,那么这应该适合您 .
请使用Apache commons math:
注意toString()!!!!
这是因为BigDecimal转换双精确二进制形式!
这些是各种建议的方法及其失败案例 .
如果你真的想要相同的double,但是以你想要的方式舍入,你可以使用BigDecimal
四舍五入通常不是人们想要的 . 而是使用String.format()以所需格式表示它 .
对于两个舍入数字 . 非常简单,您基本上更新变量而不仅仅是DecimalFormat所做的显示目的 .
x = Math.floor(x * 100) / 100;
在你的问题中,似乎你想避免舍入数字?我认为.format()将使用half-up,afaik对数字进行舍入?
因此,如果你想要舍入,200.3456应该是200.35,精度为2.但在你的情况下,如果你只想要前2然后丢弃其余的?
您可以将它乘以100,然后转换为int(或取数字的最低点),然后再将其除以100 .
你可能会遇到与边界接近的真正大数字的问题 . 在这种情况下,转换为字符串和子字符串,它将同样容易 .