正如这里所描述的,金钱类型似乎是不鼓励的。

我的应用程序需要存储货币,我应该使用哪种数据类型?数字、金钱还是浮动?


当前回答

我保持所有的货币字段为:

数字(15,6)

使用这么多小数点数位似乎有些过分,但如果你需要处理多种货币,你就需要如此精确的转换。无论我呈现给用户什么,我总是存储到美元。这样,我就可以很容易地转换到任何其他货币,给定当天的汇率。

如果你只做一种货币,最糟糕的是你浪费了一些空间来存储一些0。

其他回答

使用BigInt将货币存储为正整数,表示以最小货币单位表示的货币价值(例如,100美分存储$1.00,100存储¥100(日元,一种零十进制货币)。这正是Stripe所做的——它是全球电子商务领域最重要的金融服务公司之一。

来源:参见https://stripe.com/docs/currencies上的“零十进制货币”

我保持所有的货币字段为:

数字(15,6)

使用这么多小数点数位似乎有些过分,但如果你需要处理多种货币,你就需要如此精确的转换。无论我呈现给用户什么,我总是存储到美元。这样,我就可以很容易地转换到任何其他货币,给定当天的汇率。

如果你只做一种货币,最糟糕的是你浪费了一些空间来存储一些0。

数值与强制2单位精度。永远不要使用float或float之类的数据类型来表示货币,因为如果你这样做,当财务报告的底线数字不正确时,人们会不高兴的。

据我所知,货币类型只是由于历史原因而被保留了下来。

举个例子:1伊朗里亚尔等于0.000030美元。如果您使用的小数位数少于5位,那么1个IRR将在转换后四舍五入为0美元。我知道我们在这里是均分的,但我认为在处理金钱问题时,越安全越好。

这不是一个直接的答案,而是一个例子,说明为什么浮动不是货币的最佳数据类型。

由于浮点数在内部的表示方式,它更容易出现舍入错误。

在我们自己的十进制系统中,除2和5之外的任何数都会有四舍五入误差,这两个数都是10的因数。在二进制中,它只有2而不是5,所以即使是“干净的”小数,比如0.2(1/5)也有风险。

如果你尝试以下方法,你就会看到这个结果:

select
    0.1::float + 0.2::float as floats,          --  0.30000000000000004
    0.1::numeric + 0.2::numeric as numerics     --- 0.3
;

这就是那种让审计师抓狂的事情。

使用存储为bigint的64位整数

存储在小货币单位(美分)中,如果美分不够细,则使用大乘数来创建更大的整数。我建议你用100万美元除以100万美元。

例如:$ 5123.56可以存储为5123560000微美元。

使用简单,与每种语言兼容。 精确到可以处理一分钱的分数。 适用于非常小的单位定价(如广告印象或API费用)。 用于存储的数据大小小于字符串或数字。 易于通过计算和在最终输出时应用舍入来保持精度。