简体   繁体   English

在Java的UI中显示资金的正确方法是什么?

[英]What's the proper way to show money in an UI in Java?

On the backend I'm storing money values in a Money class which wraps a BigDecimal and sets rounding to be always Half Even with scale 8. All basic operations work fine and behave as expected. 在后端,我将Money值存储在Money类中,该类包装一个BigDecimal并将舍入值始终设置为小数位数为8的Half Even。所有基本操作都能正常工作,并且按预期运行。 But I need to show those values to the user with scale of 2, and that's bringing me rounding errors. 但是我需要以2的比例向用户显示这些值,这给我带来了舍入误差。

For example, I have these values in the backend: 例如,我在后端有这些值:

a = 109.11432 一个= 109.11432
b = 9015.57069 b = 9015.57069
c = 9124.68501 c = 9124.68501

Each one of them is formatted to the pt-BR locale: 其中每个都格式化为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;

And then I have 然后我有

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

And that's ok, at first. 没关系,首先。 But c should be a + b. 但是c应该是a + b。 With the real values, this is guaranteed, but the rounding gives me a 0.01 error. 使用实际值可以保证,但是四舍五入给了我0.01的误差。

What's the proper way to handle this situation? 处理这种情况的正确方法是什么?

It seems to be doing exactly what you want it to. 它似乎完全按照您想要的去做。 The way you are storing it, you are storing far beyond 0.01. 存储方式远远超出了0.01。 If that is not your intention, then stop doing it :) 如果这不是您的意图,请停止这样做:)

If you want a + b to equal c with 2 decimal places, then you need to round before doing the addition. 如果希望a + b等于c并保留小数点后2位,则在进行加法之前需要四舍五入。 The solution to your issue depends on the requirements of your application. 解决问题的方法取决于应用程序的要求。 One common way of storing money is actually with an integer. 一种常见的存钱方式实际上是使用整数。 That way, you cannot store fractions and you could never have the issue you are currently describing. 这样,您将无法存储分数,也永远不会遇到当前正在描述的问题。

But it really depends on your requirements. 但这确实取决于您的要求。 Are you required to do money arithmetic based on 0.01, or on full accuracy and then round the end result? 您是否需要根据0.01或完全准确度进行货币算术,然后舍入最终结果? That's a business question, not a technical question. 这是一个业务问题,而不是技术问题。

Note that a NumberFormat also can have a rounding mode . 请注意, NumberFormat 可以具有舍入模式

But ultimately, no rounding method can fulfill a business requirement like "these values have to add up to this one" without being designed specifically for that case. 但是最终,如果没有专门针对这种情况进行设计,则没有一种舍入方法可以满足“这些值必须累加起来”这样的业务要求。 Round-half-even is designed to avoid a large-scale bias, not single last-decimal errors. 半双半周期旨在避免大规模偏差,而不是单个最后十进制误差。 So where do you originally get the data from? 那么,您最初是从哪里获得数据的呢? That's where you have to make sure that the rounding preserves the total. 那是您必须确保四舍五入保留总数的地方。

Is storing the data with 8 fractional digits really a requirement, since you display only 2? 由于只显示2位,是否真的需要存储8位小数的数据? I'd also question the assumption that "With the real values, this is guaranteed", since the same thing could happen there, when rounding to 8 digits after whatever calculation produced the values. 我还要质疑“具有真实值,这是可以保证的”的假设,因为在进行任何计算得出值后四舍五入到8位数字时,可能会发生同样的事情。

If I were writing a money class, I would make it consist of two integer portions - dollars and cents (or reais and centavos, or whatever). 如果我正在写一个货币类,我将使它由两个整数部分组成-美元和美分(或雷亚尔和美分,或其他)。 That way you never end up with fractional cents. 这样,您永远都不会得到小数美分。 You just have to handle rolling over 100 cents in the addition and subtraction operations. 您只需要在加减运算中处理超过100美分的滚动。

EDIT: 编辑:

The comment to my original response has a good point. 对我的原始答复的评论很有意义。 Another option would be to just store the number of cents, then divide by 100 when you need to display. 另一种选择是只存储美分,然后在需要显示时除以100。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 Java 中存储应用程序的 conf 数据的正确方法是什么? - What is the proper way to store app's conf data in Java? 用Java编写自己的事件的正确方法是什么 - What's proper way to make my own events in java 在Java中声明项目常量的正确方法是什么? - What's the proper way of declaring project constants in Java? Java Swing-做基于阶段的GUI的正确方法是什么? - Java Swing - What's the proper way of doing a stage based GUI? 在 java 的 exec 上关闭流的正确方法是什么? - what is the proper way to close streams on java's exec? Java:将String转换为有效金额的正确方法是什么(BigDecimal) - Java: What is the right way to convert String into a valid amount of money(BigDecimal) 设置 JLabel 以显示图像的正确方法是什么? - What is the proper way to set a JLabel to show an image? 在 Java 语言中以一种或另一种方式初始化 static 变量的正确方法或潜在区别是什么? - What's the proper way or underlying difference of initializing a static variable in one way or another in Java language? 用MapDB创建数据库的正确方法是什么? - What's the proper way to create a DB with MapDB? 共享界面的正确方法是什么? - What's the proper way to share the interface?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM