Java 大十进制加错值
我有一个Java 大十进制加错值,java,bigdecimal,Java,Bigdecimal,我有一个BigDecimal定义如下: private static final BigDecimal sd = new BigDecimal(0.7d); 如果我打印它,我会得到以下值: 0.6999999999999999555910790149937383830547332763671875 这导致了一些错误的计算。有人知道如何将0.7的精确值作为BigDecimal?将其更改为0.71将查看正确的结果,但不应是这样的使用字符串文字: private static final BigD
BigDecimal
定义如下:
private static final BigDecimal sd = new BigDecimal(0.7d);
如果我打印它,我会得到以下值:
0.6999999999999999555910790149937383830547332763671875
这导致了一些错误的计算。有人知道如何将0.7
的精确值作为BigDecimal
?将其更改为0.71
将查看正确的结果,但不应是这样的使用字符串文字:
private static final BigDecimal sd = new BigDecimal("0.7");
如果使用双精度,则实际调用。没有得到0.7的原因是它不能用double
精确表示。有关详细信息,请参阅链接的JavaDoc。使用字符串文字:
private static final BigDecimal sd = new BigDecimal("0.7");
如果使用双精度,则实际调用。没有得到0.7的原因是它不能用
double
精确表示。有关更多信息,请参阅链接的JavaDoc。您应该使用声明的字符串文本值,例如new BigDecimal(“0.7”)代码>您应该使用声明的字符串文本值,例如新的BigDecimal(“0.7”)代码>以下是三种方法:
private static final BigDecimal sd = new BigDecimal("0.7");
private static final BigDecimal sd = new BigDecimal(0.7d, MathContext.DECIMAL32);
private static final BigDecimal sd = new BigDecimal(0.7d, MathContext.DECIMAL64)
这里有三种方法:
private static final BigDecimal sd = new BigDecimal("0.7");
private static final BigDecimal sd = new BigDecimal(0.7d, MathContext.DECIMAL32);
private static final BigDecimal sd = new BigDecimal(0.7d, MathContext.DECIMAL64)
如果您费心阅读文档,即您正在使用的javadoc,您可能已经知道答案了
当必须将double
用作BigDecimal
的源时,请注意此构造函数提供了精确的转换;它不会给出与使用方法然后使用构造函数将双精度
转换为字符串
相同的结果。要获得该结果,请使用static
方法
然后,当您查看的javadoc时,您会发现:
注意:这通常是将double
(或float
)转换为BigDecimal
的首选方法,因为返回的值等于从使用的结果构造BigDecimal
得到的值
这就是你的答案:使用BigDecimal.valueOf(0.7d)
,而不是新的BigDecimal(0.7d)
也许如果你费心阅读文档,即你正在使用的javadoc,你已经知道答案了
当必须将double
用作BigDecimal
的源时,请注意此构造函数提供了精确的转换;它不会给出与使用方法然后使用构造函数将双精度
转换为字符串
相同的结果。要获得该结果,请使用static
方法
然后,当您查看的javadoc时,您会发现:
注意:这通常是将double
(或float
)转换为BigDecimal
的首选方法,因为返回的值等于从使用的结果构造BigDecimal
得到的值
所以这就是你的答案:使用BigDecimal。valueOf(0.7d)
,而不是新的BigDecimal(0.7d)
从双精度构造一个BigDecimal
非常复杂。首先,它只能通过字符串的迂回来完成。(使用double
和MathContext
的构造函数是不可能正确的。我已经尝试了很多。最新的情况是,小数点前的位数由于四舍五入而需要更改,这变得很困难。因此Javadoc中警告您不应该使用它。)
但是,即使在那里,仅使用简单的String.format()
也是不够的,因为String.format()
对默认的Locale
敏感,并根据系统/VM设置输出不同的十进制分隔符,而BigDecimal
构造函数总是需要一个点作为十进制分隔符。因此,您必须使用Locale.US
构建自己的格式化程序。如果您已启动并运行此功能,则会收到未关闭资源的警告
我发现这是可行的:
static BigDecimal toBigDecimal(double value, int decimalPlaces) {
String format = "%." + decimalPlaces + "f";
try (Formatter formatter = new Formatter(Locale.US)) {
String formatted = formatter.format(format, value).toString();
return new BigDecimal(formatted);
}
}
从double
构造BigDecimal
非常复杂。首先,它只能通过字符串的迂回来完成。(使用double
和MathContext
的构造函数是不可能正确的。我已经尝试了很多。最新的情况是,小数点前的位数由于四舍五入而需要更改,这变得很困难。因此Javadoc中警告您不应该使用它。)
但是,即使在那里,仅使用简单的String.format()
也是不够的,因为String.format()
对默认的Locale
敏感,并根据系统/VM设置输出不同的十进制分隔符,而BigDecimal
构造函数总是需要一个点作为十进制分隔符。因此,您必须使用Locale.US
构建自己的格式化程序。如果您已启动并运行此功能,则会收到未关闭资源的警告
我发现这是可行的:
static BigDecimal toBigDecimal(double value, int decimalPlaces) {
String format = "%." + decimalPlaces + "f";
try (Formatter formatter = new Formatter(Locale.US)) {
String formatted = formatter.format(format, value).toString();
return new BigDecimal(formatted);
}
}
使用双精度检查构造函数逻辑,您将了解此转换之间的困难;)感谢所有的答案,但我真的不明白为什么转换失败。我想如果位数超过精度,我只会用双精度得到错误的值。0.7应为0.7,且double d=0.7d;浮动f=新浮动(0.7);系统输出打印ln(f);系统输出打印ln(d)代码>在两种情况下都精确打印0.7。双d=0.7d
不要简单地存储像int=0
dec=7
这样的值,而是使用使用使用指数的尾数逻辑,反向逻辑用于创建BigDecimal
。在这种情况下,从源代码到double的转换是不精确的,浮点值精度会丢失。从(不精确的)double到BigDecimal的转换是精确的。@XtremeBaumer:很明显,您不完全理解像double