货币数据建模¶
概述¶
MongoDB里面的数字字段类型是IEEE 754标准定义的64位浮点数以及32位或64位有符号整数。而一些金融或财务方面的应用经常需要存储一些货币的小数点值。但是当前计算机内实现的浮点数计算能力往往不能满足金融代数的要求。另外浮点数也无法准确地表示1/3或者1/10这样的分数。
这篇文章描述了两种对货币数据的建模方法。
准确精度的应用场景¶
如果你经常需要在服务器端做一些对货币数值的数学计算,那么严格精度可能会更合适一点。例如:
假如你需要对货币数值做完全一致的匹配,那么可以考虑使用 准确精度。
假如你需要做一些服务器端的计算,如 $inc, $mul, 和 aggregation framework arithmetic, 那么可以使用 准确精度。
任意精度模式的应用场景¶
如果没有在服务器端对货币数值进行计算的需要,那么使用任意精度模式的方式可能更为适合一点。例如:
准确精度¶
使用准确精度建模:
确定货币值需要的最高精度。比如说,你的应用程序可能使用十分之一美分作为最小单位。
把带小数货币值乘以10的次方数以转换成一个整数。如果最高精度要求是十分之一美分,那么就可以把值乘以1000。
保存转换以后的整形数。
例如, 下面这个例子把 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.
对货币值的放大因子(乘数)对于一种货币来说是一致的并且应用程序能够确定这个放大因子。
当使用这个模式的时候,应用程序必须始终一致的执行相应值得换算。
对这种模式的使用场景,参见 准确精度的应用场景。
任意精度¶
使用任意精度方式建模时,我们需要用两个字段来保存货币值:
在一个字段里,把货币值原样不动的按照非数字字段进行存储,如 BinData 或者 string。
在另一个字段里,以双精度浮点数近似值的形式保存所需货币值。
下述例子使用任意精度模式来保存价格字段 9.99 USD 和费用字段 0.25 USD :
{
price: { display: "9.99", approx: 9.9900000000000002, currency: "USD" },
fee: { display: "0.25", approx: 0.2499999999999999, currency: "USD" }
}
适当使用的话,应用程序可以执行对货币字段按近似字段的值进行范围查找和排序。然而,使用近似字段查询排序时应用程序必须做一些后续处理来对非数字型的货币值进行解码转换成数字,然后返回给客户端。
对于这种方式的应用场景,参见 任意精度模式的应用场景。