股票价格的 BigDecimal?
我意识到我们应该对所有货币值使用 BigDecimal,但是以美元表示的股票价格又如何呢?
我注意到主要供应商的数据馈送 API 使用 double
类型来表示股票报价。有谁知道为什么?
这是否意味着我的应用程序可以使用 double
类型来存储来自这些供应商的股票报价?
I realize that we should use BigDecimal
for all monetary values, but what about stock prices in dollars?
I noticed that data feed API from major vendors uses the type double
for stock quotes. Does anyone know why?
Does that mean my application can use the type double
to store stock quotes that come from these vendors?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
货币不使用二进制浮点的原因是货币使用小数,而人们(和会计法规)期望对其执行的算术运算产生特定的小数行为 - 二进制浮点不提供这种行为。
然而,股票报价源通常不用于会计。它们被显示、比较,用作各种图表分析指标或交易算法的输入——所有这些都比会计更接近科学应用,并且不需要小数行为或精度。相反,由于数据量很大,存储效率和性能是相关的,而 BigDecimal 在这些方面确实很糟糕。
The reason for not using binary floating-point for money is that money uses decimal fractions and people (and accounting regulations) expect specific decimal behaviour from arithmetic operations performed on it - which binary floating-point does not provide.
However, stock quote feeds aren't generally used for accounting. They're displayed, compared, used as input for various chart analysis indicators or trading algorithms - all much closer to scientific applications than accounting, and not requiring decimal behaviour or precision. Instead, because of the large amount of data, storage efficiency and performance are relevant, and
BigDecimal
really sucks at those.我在外地工作。从精度角度来看,BigDecimal 显然是理想的,但从性能角度来看,它很糟糕。在某些情况下,双倍是一种选择(特别是在处理正常股票价格时,双倍很容易 - 只要采取适当的预防措施 - 就能代表我经常处理的所有股票交易所的整个价格范围)。
另一种选择是,如果您知道相关交易所使用的 DP 范围,则使用定点和普通 int 或 long。举个我很熟悉的例子,Xetra(德国电子交易所)目前最多有3位小数。使用 3dp,您可以使用普通 int 表示最高 2,147,483.647 的价格。对于单个价格来说还不错,但对于代表一天的交易总量来说就不好了。
问题在于您接收到的数据是什么、数据的精度是多少以及您如何处理它。
I work in the field. BigDecimal is obviously ideal from a precision perspective, but it sucks from a performance perspective. doubles are an option in some circumstances (particularly when dealing with normal equity prices, doubles are easily - with appropriate precautions - able to represent the entirety of the price range of all the equity exchanges I regularly deal with).
Another option is, if you know the range of DP used by the exchanges in question, to use fixed-point and a normal int or long. To take an example I know well, Xetra (the German electronic exchange) currently has at most 3 decimal places. Using 3dp, you can represent prices up to 2,147,483.647 with a normal int. Fine for an individual price, no good for representing the total of a day's trading.
It's all a question of what data you're receiving, what the precision of that data is and how you're processing it.
我拒绝使用 BigDecimal 来表示货币值(一般来说*)。使用设计用于货币的数据类型(具有最低精度,例如美元的密耳),并知道如何处理其他规则。这也可以用于防止美元“意外”兑换成日元等。
Joda Money 或 timeandmoney 就是两个这样的例子。
虽然 BigDecimal 在解决固定精度方面比 double 好得多,但在我看来,它仍然不是正确的货币表示形式。 (BigDecimal 可能是后端 [或者它可以完全替换为另一个实现。],作为前端,它不能充分代表域。)
快乐编码。
*正如其他人所说,这取决于用途。
I reject the use of BigDecimal for monetary values (in general*). Use a data-type designed for use with currency (which has a minimum precision such as mils for USD) and knows how to handle other rules. This can also be used to prevent "accidental" conversion of USD to Yen, etc.
Joda Money or timeandmoney are two such examples.
While a BigDecimal is far better than a double for addressing a fixed precision, it is still not a correct monetary representation IMOHO. (BigDecimal may be the back-end [or it could be entirely replaced with another impl.], as a front-end it doesn't adequately represent the domain.)
Happy coding.
*As others have said, it depends upon the use.
就我个人而言,我会坚持使用 BigDecimal。供应商使用双打有点令人不安,但您没有理由传播他们的错误。您将从“稍差”的数据开始,但至少在您对这些值执行的任何操作中都不会引入进一步的意外行为。
您可能想与供应商交谈并找出他们为什么使用双打......
Personally I would stick to
BigDecimal
. It's somewhat disturbing that the vendors are using doubles, but there's no reason why you should propagate their mistake. You'll start with "slightly bad" data, but at least you won't introduce further unexpected behaviour in whatever you do with the values.You might want to talk to the vendors and find out why they're using doubles though...
对此的一个猜测:
当这样的 API 使用基于文本的格式(如 XML 或 JSON)时,传输的数据实际上不是双精度数,而是十进制数 - 而十进制数就是这里的意思。通常,在某些 API 中,double 是唯一支持十进制数(小数点后带有数字)的数据类型。
当您收到双精度的股票价格并想要“以货币方式”计算它时,请确保您知道它有多少小数位(小数点后)(应该有 - 不是来自双精度,而是来自股票价格),并用这个比例将其转换为 BigDecimal(或任何您用于货币计算的值)。
A guess on this:
When such a API uses a text-based format (like XML or JSON), the data transmitted are actually not double, but decimal numbers - and decimal numbers is what is meant here. And often double is the only datatype which supports decimal numbers (with digits after the point) in some of these APIs.
When you receive a stock price as double and want to calculate "in a money way" about it, make sure you know how much decimal digits (after the point) it has (should have - not from the double, but from the type of stock price), and convert it with this scale to a BigDecimal (or whatever you are using for money calculations).