OPTIONS
翻译或纠错本页面

货币数据建模

概述

MongoDB里面的数字字段类型是IEEE 754标准定义的64位浮点数以及32位或64位有符号整数。而一些金融或财务方面的应用经常需要存储一些货币的小数点值。但是当前计算机内实现的浮点数计算能力往往不能满足金融代数的要求。另外浮点数也无法准确地表示1/3或者1/10这样的分数。

注解

本文提及的数学计算指的是在服务器端由 mongod or mongos 执行的计算而非客户端的计算。

这篇文章描述了两种对货币数据的建模方法。

  • 准确精度 把货币值乘以10的次方数。

  • 任意精度 使用两个字段,一个字段以非数字形式保存真实地货币数值,一个字段则以浮点数的形式保存这个货币数值的大约值。

准确精度的应用场景

如果你经常需要在服务器端做一些对货币数值的数学计算,那么严格精度可能会更合适一点。例如:

任意精度模式的应用场景

如果没有在服务器端对货币数值进行计算的需要,那么使用任意精度模式的方式可能更为适合一点。例如:

  • 如果你需要处理任意的或者未知的精度,参见 任意精度

  • 如果服务器端的近似值计算可以满足要求,或者能够利用客户端作进一步处理,那么也可以使用 任意精度

准确精度

使用准确精度建模:

  1. 确定货币值需要的最高精度。比如说,你的应用程序可能使用十分之一美分作为最小单位。

  2. 把带小数货币值乘以10的次方数以转换成一个整数。如果最高精度要求是十分之一美分,那么就可以把值乘以1000。

  3. 保存转换以后的整形数。

例如, 下面这个例子把 9.99 USD 乘以1000进行放大并得到9990。

{ price: 9990, currency: "USD" }

这个模型假设对于一个特定的货币值:

  • The scale factor is consistent for a currency; i.e. same scaling factor for a given currency.
  • 对货币值的放大因子(乘数)对于一种货币来说是一致的并且应用程序能够确定这个放大因子。

当使用这个模式的时候,应用程序必须始终一致的执行相应值得换算。

对这种模式的使用场景,参见 准确精度的应用场景

任意精度

使用任意精度方式建模时,我们需要用两个字段来保存货币值:

  1. 在一个字段里,把货币值原样不动的按照非数字字段进行存储,如 BinData 或者 string

  2. 在另一个字段里,以双精度浮点数近似值的形式保存所需货币值。

下述例子使用任意精度模式来保存价格字段 9.99 USD 和费用字段 0.25 USD :

{
  price: { display: "9.99", approx: 9.9900000000000002, currency: "USD" },
  fee: { display: "0.25", approx: 0.2499999999999999, currency: "USD" }
}

适当使用的话,应用程序可以执行对货币字段按近似字段的值进行范围查找和排序。然而,使用近似字段查询排序时应用程序必须做一些后续处理来对非数字型的货币值进行解码转换成数字,然后返回给客户端。

对于这种方式的应用场景,参见 任意精度模式的应用场景