如何用浮点运算解决精度误差

时间:2016-03-01 14:57:50

标签: java math currency floating-accuracy

我正在尝试制作一个计算给定金额的等价变化量的程序。程序中的所有内容都运行良好,直到我得到便士。当我得到便士时,我已经做了很多浮点算术,这个值变得不准确。这是输出:

enter image description here

我们可以看到,而不是0.2(我将除以0.1得到2,正确答案),我们有019999999999959064(当除以0.01得到便士数量时,我们得到1而不是2) 。如何解决这个问题,以便获得正确数量的便士?

4 个答案:

答案 0 :(得分:7)

你不能。浮点不是建模确切货币价值的好选择。

使用long类型并使用便士,或(ii)使用专门用于模拟金钱的类。

答案 1 :(得分:2)

诽谤

停止使用浮点代表货币。 BigDecimal同样糟糕,但精度较低(可能没有)。

如果您使用BigDecimal, 我建议您在代码中包含以下注释:

// Danger, this code written by a goofball (insert your name here).

真正的解决方案

使用long并表示从一分钱的有意义(对你的情况)开始的值;也许是一分钱的1000分。 即使你代表一分钱的1,000,000, 很长一段时间仍然提供了足够的空间 $ 9,223,372,036.99 这可能比您需要处理的任何交易都要大。

答案 2 :(得分:1)

您需要使用适当的舍入。即使您使用longBigDecimal舍入问题也不会消失,但在这种情况下它会更简单。

一个好的起点是四舍五入到long分。

double value = 586.67;
long v = Math.round(value * 100.0); // the fact you used a double is fine.
long hundreds = v / 100;
v -= hundreds * 100;
long fifties = v / 50;
v -= fifties * 50;
long twenties = v / 20;
v -= twenties * 20;
long tens = v / 10;
v -= tens * 10;

你可以用double做到这一点,但是你需要绕过每一步,这在这个例子中更复杂。

答案 3 :(得分:0)

Math.round是解决这个问题的一种方法,但我不推荐它。

另一种方法是使用BigDeciaml,这在处理货币时非常准确,

我最近阅读的另一种方式是直到最后工作,例如以美分而不是美元工作,因此$ 1将是100而不是在那里工作。

我希望这些想法有所帮助

cifar10.py

very intereesting video on floating points in general