8

在数据库中存储货币/货币价值,在服务器端应用程序中处理它们,最后通过 JSON API 将它们发送到浏览器的最佳实践是什么?

我想出了两种方法,但我不确定如何权衡利弊:

以最小货币单位将值存储为整数

  • 基本上这意味着数据库将以美分/派斯/先令/等为单位存储货币价值。
  • 服务器端应用程序将此值映射到常规整数变量。
  • JSON API 将值表示为常规 JSON 数字。
  • 这种方法的缺点是在向用户显示货币值之前必须不断地除以 100,并且在存储任何用户输入之前总是乘以 100。
  • 可能的陷阱:你如何定义最小的货币单位?它是基于两位小数还是四位?是否有任何货币没有 100:1 的比率,即 100 美分 = 1 美元。

将值存储为具有固定精度和比例的十进制/数字

  • DB 将货币值存储为具有固定精度和比例的小数/数字类型,例如。数字(10,2)
  • 服务器端应用程序将这些映射到特殊对象,这些对象可以保持计算的精度和规模,例如。BigDecimal在红宝石。
  • JSON API 将这些值交换为字符串而不是数字。因为数字会被 JSON 解析器自动解析为浮点数,从而导致精度损失。
  • 这种方法的缺点是服务器端的所有计算都需要在盒装数据类型中进行(可能更慢),并且 JSON 解析器需要意识到某些字符串实际上不是字符串,而是数字的事实价值观。
  • 这样做的好处是您不需要不断地乘以和除以 100。

是否有普遍接受的最佳实践?

4

1 回答 1

4

这两种做法还有两个额外的陷阱。

首先,并非所有货币都需要两位小数。许多人需要三个。更多需要零。而一些特定领域的应用程序,例如金融和外汇,需要 5 或 6 个。

其次,一些货币的小面额兑换率也很丰富。例如,老式卢比兑换成 16 安娜、64 派萨或 192 派。幸运的是,如果维基百科可以参考的话,只有两个国家保持这种疯狂的转化率——毛里塔尼亚 1 ouguiya = 5 khoums,马达加斯加 1 ariary = 5 iraimbilanja。

http://en.wikipedia.org/wiki/Decimalisation

不过,关键是,如果您打算本地化您的应用程序,您的假设不应过于以美国为中心。至少,考虑一下你有 0、2 和 3 位小数的用例,并仔细考虑一下如果你曾经走向国际,你想走哪条路。以防万一。

顺便说一句,还要注意numericPostgres 中的类型可以在不指定精度的情况下存储。这样做不需要更多空间,因为当它太大时它会驻留在扩展存储中。而且,就像varchar比 更好varchar(n),它会更快,因为您将在存储数字时跳过内置的精度检查(在这种情况下,确实需要保持理智)。

至于您描述的两种方法中哪一种最好,我已经看到了更多第二种方法——以简化的形式。

我要强调三点:

  1. 为了在生成帐户和报告时不引入舍入错误,在数据库中将货币存储为numeric,无论是否具有精度都是有意义的。(也有一个内置的货币类型,但我从未见过它出于各种非常正当的原因在实践中使用。)

  2. 如果您确实需要溢出 bigint 或双精度浮点数的精度(如果有内存,js 和 json 将后者用于浮点数),那么速度应该是您最不必担心的问题。如果这是您的情况,那么从一端到另一端,任意精度的数学就是要走的路。

  3. 操纵典型货币金额的典型应用程序永远不会遇到这些溢出限制。冷眼看这里。除非您打算存储数以万亿美元计的金额,否则将无界数字转换为字符串并返回以在 json 中传递它们是您过度设计应用程序的标志。如果是这种情况,只需坚持使用双精度浮点数并发布您的应用程序。

于 2013-05-02T13:42:25.403 回答