对我来说,Double 似乎应该遵循与 MathContext.DECIMAL64 中使用的 IEEE 标准相同的规则,但是,在这种情况下,我会得到不同的行为:
import java.math.BigDecimal;
import java.math.MathContext;
public class BigDecimalTest {
public static void main(String[] args) {
double foo = 8.7;
System.out.println(new BigDecimal(foo, MathContext.DECIMAL64));
System.out.println(new BigDecimal(Double.toString(foo)));
}
}
输出:
8.699999999999999
8.7
最佳答案
A BigDecimal 任意精度带符号的十进制数。另一方面,double 是一个 float ,因此它暗示了对所表示的数字的一些印象。
当您尝试从 double 创建 Bigdecimal 时,您会得到 de double 表示的值,在您的示例中为 8.699999999999999。原因是 double 变量并不能真正保持准确的 8.7。有关大小数的更多信息,请访问
当您将数字表示为字符串时,“8.7”值由 to string 方法返回,这就是分配给 Bigdecimal 的值。方法 toString 使用一些 roools 将 double 值表示为 String 看看
当您使用 MathContext.DECIMAL64 时,您是在说“好吧,我知道双数存在一些缺陷,所以我希望您使用 16 位的精度和四舍五入模式进行四舍五入”而这正是您得到的结果. Java 取 8.7 的 double 表示即 8.6999999999999993 并将其四舍五入为 16 位结果为 8.699999999999999 因为数字 17 是“3”,因此四舍五入的结果是保留数字 16,因为它是 9。
有关 MathContext.DECIMAL64 含义的信息: http://goo.gl/fVUehh
如果你想得到 8.7,只需使用低于 16 位的精度。
示例代码
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
double foo = 8.7;
System.out.println(new BigDecimal(foo, MathContext.DECIMAL64));
System.out.println(new BigDecimal(foo, new MathContext(16)));
System.out.println(new BigDecimal(foo, new MathContext(17)));
System.out.println(new BigDecimal(foo, new MathContext(1)));
System.out.println(new BigDecimal(foo, new MathContext(2)));
System.out.println(new BigDecimal(foo, new MathContext(3)));
System.out.println(new BigDecimal(foo, new MathContext(15)));
System.out.println(new BigDecimal(Double.toString(foo)));
}
输出
8.699999999999999
8.699999999999999
8.6999999999999993
9
8.7
8.70
8.70000000000000
8.7
关于 BigDecimal 和 double 的更多信息
https://blogs.oracle.com/CoreJavaTechTips/entry/the_need_for_bigdecimal
关于java - 为什么在 Java 中构造 BigDecimal 时 Double.toString 的行为与 MathContext.DECIMAL64 不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19431689/