[英]Different result in RoundingMode.HALF_UP
Please comment me freely. 请自由评论我。 What was wrong in the following program.
以下程序出了什么问题。 It is giving different round result.
它给出了不同的圆形结果。
public class Test {
public static String round(double value, int places) {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.toPlainString();
}
public static void main(String[] args) throws Exception {
double value1 = 1.1234565;
System.out.println(round(value1, 6));
double value2 = 1.1235;
System.out.println(round(value2, 3));
}
}
Why it is out put like that? 为什么这样出来?
1.123457
1.123 --> Actually, I expect 1.124
In Doc(eclipse) 在Doc(eclipse)
You're calling the BigDecimal(double)
constructor. 你正在调用
BigDecimal(double)
构造函数。 That's documented as: 这记录为:
Translates a double into a BigDecimal which is the exact decimal representation of the double's binary floating-point value.
将double转换为BigDecimal,它是double的二进制浮点值的精确十进制表示形式。 The scale of the returned BigDecimal is the smallest value such that (10scale × val) is an integer.
返回的BigDecimal的比例是最小值,使得(10scale×val)是整数。
The notes are illuminating too, and I suggest you read them. 这些笔记也很有启发性,我建议你阅读它们。
The value you're passing in is exactly 1.12349999999999994315658113919198513031005859375, as that's the closest double
to 1.1235. 您正在传递的价值是完全1.12349999999999994315658113919198513031005859375,因为这是最接近的
double
至1.1235。 You can see that if you print out bd.toPlainString()
before calling setScale
. 如果在调用
setScale
之前打印出bd.toPlainString()
,则可以看到。 Therefore, that isn't half-way between 1.123 and 1.124 - it's closest to 1.123. 因此,这不是 1.123和1.124之间的中间 - 它最接近1.123。
If you want a BigDecimal
value of exactly 1.1235, I suggest you pass it as a String
instead: 如果你想要
BigDecimal
值恰好是 1.1235,我建议你把它作为String
传递:
import java.math.*;
public class Test {
public static String round(String value, int places) {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.toPlainString();
}
public static void main(String[] args) throws Exception {
String value1 = "1.1234565";
System.out.println(round(value1, 6));
String value2 = "1.1235";
System.out.println(round(value2, 3));
}
}
Alternatively you could use BigDecimal.valueOf(double)
instead of new BigDecimal(double)
- but then you still have the problem that you've converted your real original source data (the text in your source code) into a binary floating point number first, potentially losing information. 或者你可以使用
BigDecimal.valueOf(double)
而不是new BigDecimal(double)
- 但是你仍然遇到的问题是你已经将真正的原始源数据(源代码中的文本)转换为二进制浮点数,可能会丢失信息。
The problem is you are using to exact represention of the double
including any representation error. 问题是你正在使用精确的
double
表示,包括任何表示错误。 A simple solution is to use the value you would get from the double
if it was printed. 一个简单的解决方案是使用打印时从
double
获得的值。
public static String round(double value, int places) {
return BigDecimal.valueOf(value)
.setScale(places, RoundingMode.HALF_UP);
.toPlainString();
}
BigDecimal.valueOf
uses the simplest value which would be represented as the double
you have. BigDecimal.valueOf
使用最简单的值,该值将表示为您拥有的double
BigDecimal.valueOf
值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.