用什么类来表示货币?

48

为了避免大多数舍入误差,我应该使用什么类来表示货币?

我应该使用Decimal还是简单的内置number

是否有现成的Money类支持货币转换,可以供我使用?

有什么陷阱我应该避免吗?


我一直认为货币转换只是乘法。 - SilentGhost
3
@SilentGhost: 是的也不是。你必须考虑你将如何使用所拥有的价值。当你去年支付了U$S2000 + AR$6300 + €1500,今年支付了U$S4000 + AR$1200 + €500时,你该怎么做?有许多事情要考虑,因此“Money”对象需要保存历史价值和当前价值。 - Esteban Küber
9
需要翻译的内容:Pitfall to avoid: using floating point numbers. See Office Space.应避免的陷阱:使用浮点数。参见《办公空间》电影。 - user142019
6个回答

39

不要使用浮点数来表示货币。浮点数不能准确地表示十进制数。你会遇到复合舍入误差的噩梦,并且无法可靠地转换货币。请参见马丁·福勒(Martin Fowler)关于此主题的简短文章

如果你决定编写自己的类,我建议以十进制数数据类型为基础。

我认为python-money不是一个好选择,因为它已经很久没有维护了,而且它的源代码中有一些奇怪和无用的代码,兑换货币也很难使用。

试试py-moneyed。它比python-money更好。


3
十进制是基于浮点数的,我想知道它是如何解决问题的。 - xenoterracide
2
如何解决或绕过浮点数问题在Python的decimal文档的第一部分中有描述:https://docs.python.org/3/library/decimal.html希望这能有所帮助。 - NeverCast

18

9
由于十进制数的精度处理方式不适合,假设您正在处理小于10亿美元且精度为0.01美元的金额,则需告知十进制库您的数字长度不超过12位。现在您有两个问题:代码无法处理恶性通货膨胀;而0.01将显示为“0.010000000000”。 - Pitarou
@Pitarou,请原谅我的无知,但是为什么您会降低精度,特别是在可能遇到恶性通货膨胀的应用程序中?而且您如何得到$0.01的输出?我尝试了decimal.getcontext().prec = 12; print(decimal.Decimal('0.01')),但它打印出没有尾随零的0.01。即使您确实获得了该输出,为什么不在显示之前四舍五入呢? - wjandrea

10

5
看了一下http://code.google.com/p/python-money/source/browse/trunk/money/Money.py,我发现他们确实在内部使用`Decimal` :) - Esteban Küber

6
你可以看一下这个库:python-money。由于我没有使用过,无法对其有所评论。
处理货币为整数的“技巧”:
  • 将货币乘以100/除以100(例如$100.25 -> 10025),以得到“分”的表示方式。

9
许多会计系统追踪的东西比分到分钱还要精确。 - Paul McMillan
真的,但一切都取决于需求...在这个帖子中提到的QuantLib库似乎是进行“严肃”金融工作的好选择。 - ChristopheD

5

一个简单、轻量级但可扩展的想法:

class Money():

    def __init__(self, value):
        # internally use Decimal or cents as long
        self._cents = long(0)
        # Now parse 'value' as needed e.g. locale-specific user-entered string, cents, Money, etc.
        # Decimal helps in conversion

    def as_my_app_specific_protocol(self):
        # some application-specific representation

    def __str__(self):
        # user-friendly form, locale specific if needed

    # rich comparison and basic arithmetics
    def __lt__(self, other):
        return self._cents < Money(other)._cents
    def __add__(self, other):
        return Money(self._cents + Money(other)._cents)

你可以:
  • 仅在你的应用程序中实现需要的功能。
  • 随着你的发展而扩展它。
  • 根据需要更改内部表示和实现。

5

如果您对与金融有关的it技术感兴趣,您可能会对QuantLib感兴趣。

它内置了处理货币类型的类,并且拥有4年的积极开发经验。


这个项目看起来很有趣,但可能有点过于复杂了,我很可能会选择一个纯Python项目来保持简单。 - Esteban Küber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接