Java二进制十进制舍入错误

Java二进制十进制舍入错误,java,android,rounding,bigdecimal,Java,Android,Rounding,Bigdecimal,我有以下函数用于在Java中舍入双精度值: public static double round(double d, int decimalPlace) { BigDecimal bd = new BigDecimal(Double.toString(d)); bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP); return bd.doubleValue(); } 作为输入,此函数将接收以下值: doub

我有以下函数用于在Java中舍入双精度值:

public static double round(double d, int decimalPlace) {

    BigDecimal bd = new BigDecimal(Double.toString(d));
    bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
    return bd.doubleValue();
}
作为输入,此函数将接收以下值:

double d = 7.3149999999999995;
int decimalPlace = 2
但是,当函数返回时,返回的值是7.31,而不是7.32。 我搜索了文档,想知道为什么bd.SetScale会有这种行为,但没有成功

有人能告诉我为什么会这样吗? 非常感谢

有人能告诉我为什么会这样吗

它遵守记录的行为:)来自:

如果操作减小了刻度,则必须将未标度的值除以(而不是乘以),并且可以更改该值;在这种情况下,指定的舍入模式应用于除法

以及:

舍入模式向“最近邻居”舍入,除非两个邻居距离相等,在这种情况下舍入

现在7.314999999995与7.31和7.32的距离并不相等——它更接近7.31,所以这就是结果

只有当原始值正好为7.315,即两者之间的一半时,才能看到
HALF_UP
HALF_DOWN
之间的差异

顺便说一句,为了确保您准确地获得您希望开始使用的数字,我建议使用
字符串
。例如:

double d = 0.1;
BigDecimal bd = new BigDecimal(d);
不等于:

BigDecimal bd = new BigDecimal("0.1");
double
转换为
BigDecimal
通常是您出错的标志,您应该始终使用一种类型

有人能告诉我为什么会这样吗

它遵守记录的行为:)来自:

如果操作减小了刻度,则必须将未标度的值除以(而不是乘以),并且可以更改该值;在这种情况下,指定的舍入模式应用于除法

以及:

舍入模式向“最近邻居”舍入,除非两个邻居距离相等,在这种情况下舍入

现在7.314999999995与7.31和7.32的距离并不相等——它更接近7.31,所以这就是结果

只有当原始值正好为7.315,即两者之间的一半时,才能看到
HALF_UP
HALF_DOWN
之间的差异

顺便说一句,为了确保您准确地获得您希望开始使用的数字,我建议使用
字符串
。例如:

double d = 0.1;
BigDecimal bd = new BigDecimal(d);
不等于:

BigDecimal bd = new BigDecimal("0.1");

double
转换为
BigDecimal
通常表明您有问题,您应该始终使用一种类型。

对半取整:取整模式向“最近邻居”取整,除非两个邻居距离相等,在这种情况下,取整

在您的示例中,最近的邻居是:7.31,因为7.314中的4比10更接近于0。要证明这一点,请更改7.314。。。到7.315


查看不同的舍入模式以提供所需的行为。

舍入半舍五入:舍入模式向“最近邻居”舍入,除非两个邻居距离相等,在这种情况下舍入

在您的示例中,最近的邻居是:7.31,因为7.314中的4比10更接近于0。要证明这一点,请更改7.314。。。到7.315



查看不同的舍入模式以提供所需的行为。

如果改为使用
7.314999995
会发生什么?可能是
5
丢失了这有什么奇怪的?它不完全在7.31和7.32之间,所以为什么要取整到7.32?@JonSkeet,我使用BigDecimal.round_HALF_up,所以,我猜它应该取整到7.32。@regisxp:但前提是值在7.31和7.32之间的一半。。。而7.31499999995并不是两者之间的一半。用7.315试试看,它会达到你期望的效果。@JonSkeet:哦,哈,这是一个很好的观点。如果你用
7.314999995
代替它会发生什么?可能是
5
丢失了这有什么奇怪的?它不完全在7.31和7.32之间,所以为什么要取整到7.32?@JonSkeet,我使用BigDecimal.round_HALF_up,所以,我猜它应该取整到7.32。@regisxp:但前提是值在7.31和7.32之间的一半。。。而7.31499999995并不是两者之间的一半。用7.315试试看,它会达到你期望的效果。@JonSkeet:哦,哈,这是一个很好的观点。另外,你可以将BigDecimal实例化为BigDecimal bd=new BigDecimal(d),而不是在BigDecimal构造函数中将d转换为字符串。否。如果在
BigDecimal
实例中的任意位置包含double,您将介绍。此外,您可以将BigDecimal实例化为BigDecimal bd=new BigDecimal(d),而不是在BigDecimal构造函数中将d转换为字符串。否。如果你在
BigDecimal
实例中的任何地方涉及到double,你将介绍它。@Anshu:我希望将来有类似问题的人都能搜索上半部或下半部,找到这个,并将他们的情况与这个进行比较…@Anshu非常感谢你的解释。问题是,另一种语言,如C#,将相同的值舍入到7.32,我需要在这里保持相同的逻辑。。。所以,我测试了所有的模式,但没有一个像我预期的那样工作…嘿!这是乔恩的解释@请发布你在.NET中使用的代码。。。你需要弄清楚到底发生了什么。请注意我关于从
double
转换为
BigDecimal
基本上是一个坏主意的观点…@regisxp:问题是之前的方法采用了
double
,这会引起大的闪烁警告灯。首先,我会放弃这个决定。@Anshu:我希望将来有类似问题的任何人都会搜索“一半向上”或“一半向下”,找到这个,并将他们的情况与这个进行比较…@Anshu非常感谢你的解释。问题是,另一种语言,如C#,将相同的值舍入到7.32,我需要在这里保持相同的逻辑。。。所以,我测试了所有的模式