在Java中用UI显示钱的正确方法是什么?

时间:2010-08-04 20:34:53

标签: java formatting currency

在后端,我将货币值存储在Money类中,该类包装了BigDecimal,并且将舍入设置为使用比例8的一半。所有基本操作都正常工作并且按预期运行。但是我需要以2的比例向用户显示这些值,这会给我带来四舍五入的错误。

例如,我在后端有这些值:

a = 109.11432
b = 9015.57069
c = 9124.68501

每个格式化为pt-BR语言环境:

NumberFormat nf = NumberFormat.getInstance();
nf.setCurrency(Currency.getInstance(new Locale("pt","BR")));
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
String n = nf.format(valor);
return n;

然后我有

a = 109,11
b = 9.015,57
c = 9.124,69

一开始就没关系。但是c应该是a + b。使用实际值,这是有保证的,但舍入给我0.01误差。

处理这种情况的正确方法是什么?

3 个答案:

答案 0 :(得分:1)

它似乎完全符合您的要求。存储它的方式,存储远远超过0.01。如果这不是你的意图,那就停止这样做:)

如果你想要一个带有2位小数的+ b等于c,那么你需要在进行加法之前进行舍入。您的问题的解决方案取决于您的应用程序的要求。存钱的一种常见方式实际上是整数。这样,您就无法存储分数,也无法解决您当前所描述的问题。

但这实际上取决于您的要求。您是否需要根据0.01或完全准确度进行货币算术,然后舍入最终结果?这是一个商业问题,而不是技术问题。

答案 1 :(得分:1)

请注意,NumberFormat 可以有rounding mode

但最终,没有舍入方法可以满足业务要求,例如“这些值必须加到这个值”,而不是专门针对该情况设计的。 round-half-even旨在避免大规模偏差,而不是单个最后十进制误差。那么你最初从哪里获取数据?这就是你必须确保舍入保留总数的地方。

存储8个小数位的数据真的是一个要求,因为你只显示2个?我还要质疑“有了实际值,这是有保证的”的假设,因为在那里计算产生数值之后四舍五入到8位数时会发生同样的事情。

答案 2 :(得分:0)

如果我正在写一个金钱类,我会让它由两个整数部分组成 - 美元和美分(或雷亚尔和分数,或其他)。这样你永远不会得到分数美分。你只需要在加法和减法操作中处理超过100美分的费用。

编辑:

对原始回复的评论有一个好处。另一个选择是只存储分数,然后在需要显示时除以100。