我正在尝试制作一个计算给定金额的等价变化量的程序。程序中的所有内容都运行良好,直到我得到便士。当我得到便士时,我已经做了很多浮点算术,这个值变得不准确。这是输出:
我们可以看到,而不是0.2(我将除以0.1得到2,正确答案),我们有019999999999959064(当除以0.01得到便士数量时,我们得到1而不是2) 。如何解决这个问题,以便获得正确数量的便士?
答案 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)
您需要使用适当的舍入。即使您使用long
或BigDecimal
舍入问题也不会消失,但在这种情况下它会更简单。
一个好的起点是四舍五入到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而不是在那里工作。
我希望这些想法有所帮助