MongoDB - 十进制类型的值怎么样?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11541939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 12:44:33  来源:igfitidea点击:

MongoDB - What about Decimal type of value?

mongodbdecimalbigdecimalbson

提问by Hymanson Tale

I am currently learning and applying MongoDB for a small financial related project.

我目前正在为一个小型金融相关项目学习和应用 MongoDB。



When I read MongoDB in Action, it says:

当我阅读MongoDB in Action 时,它说:

The only other issue that commonly arises with BSON numeric types is the lack of decimal support. This means that if you're planning on storing currency values in MongoDB, you need to use an integer type and keep the values in cents.

BSON 数字类型通常出现的唯一其他问题是缺乏小数支持。这意味着如果您计划在 MongoDB 中存储货币值,则需要使用整数类型并将值保留为美分。



My financial related product will involve some currency values, but I am little bit confused or worried about the above statement. Here are my questions:

我的金融相关产品会涉及一些货币价值,但我对上面的说法有点困惑或担心。以下是我的问题:

  1. Can I use doublefor those currency valuesin my project?
  2. What will happen or is the consequences if I directly use doublefor them?
  3. If decimal type is an must-have thing for financial product, is that a bad idea to use MongoDB?
  4. What does it mean you need to use an integer type and keep the values in cents? Does it mean that if I am going to store 1.34 dollars, then I should store 134 cents?
  1. 我可以double用于currency values我的项目中的那些吗?
  2. 如果我直接使用double它们会发生什么或后果是什么?
  3. 如果十进制类型是金融产品必备的东西,那么使用MongoDB是不是一个坏主意?
  4. 这是什么意思you need to use an integer type and keep the values in cents?这是否意味着如果我要存储1.34 dollars,那么我应该存储134 cents

Thanks

谢谢

回答by Stennie

If you want an exact representation for financial purposes, then doubles or floating point values are unsuitable as the fractional parts are subject to rounding error. Certain decimal values cannot not be represented using binary-based floating points and must be approximated.

如果出于财务目的想要精确表示,则双精度值或浮点值不合适,因为小数部分会出现舍入误差。某些十进制值不能使用基于二进制的浮点表示,必须近似。

For a less technical intro, see The trouble with rounding floating point numbers; if you want to geek out, then read What Every Computer Scientist Should Know About Floating-Point Arithmetic.

有关技术含量较低的介绍,请参阅舍入浮点数的麻烦;如果你想搞怪,那么请阅读每个计算机科学家应该知道的关于浮点运算的知识

The recommendation of using an integer type (storing the value in cents) is to avoid potential rounding errors. This approach is described as "Using a Scale Factor" in the MongoDB documentation for modelling monetary dataand is a general workaround for MongoDB 3.2 and earlier.

建议使用整数类型(以美分存储值)以避免潜在的舍入错误。这种方法在用于建模货币数据的 MongoDB 文档中被描述为“使用比例因子”,并且是 MongoDB 3.2 及更早版本的一般解决方法。

MongoDB 3.4 includes a new Decimal BSON typewhich provides exact precision for manipulating monetary data fields.

MongoDB 3.4 包含一个新的十进制 BSON 类型,它为操作货币数据字段提供精确的精度。

回答by arva

Looks like MongoDB has finally added support for decimals, although at the time of writing this is just finished development, but hopefully it should be available very soon in stable version (3.4?).

看起来 MongoDB 终于添加了对小数的支持,尽管在撰写本文时这才刚刚完成开发,但希望它很快就会在稳定版本(3.4?)中可用。

https://jira.mongodb.org/browse/SERVER-1393

https://jira.mongodb.org/browse/SERVER-1393

回答by Salvador Dali

MongoDb added support for Decimal data type in 3.4 version. It is also available from the shell.

MongoDb在 3.4 版本中增加了对Decimal 数据类型的支持。它也可以从shell 获得

3.4 adds support for the decimal128 format with the new decimal data type. The decimal128 format supports numbers with up to 34 decimal digits (i.e. significant digits) and an exponent range of ?6143 to +6144.

Unlike the double data type, which only stores an approximation of the decimal values, the decimal data type stores the exact value. For example, a decimal NumberDecimal("9.99") has a precise value of 9.99 where as a double 9.99 would have an approximate value of 9.9900000000000002131628...

3.4 使用新的十进制数据类型添加了对 decimal128 格式的支持。decimal128 格式支持最多 34 位十进制数字(即有效数字)和指数范围为 ?6143 到 +6144 的数字。

与仅存储十进制值的近似值的双精度数据类型不同,十进制数据类型存储精确值。例如,十进制 NumberDecimal("9.99") 的精确值为 9.99,而双精度 9.99 的近似值为 9.9900000000000002131628...

回答by Philipp

When you don't want to store currency as cent-values, you could store a currency of $1.34 as an object like this:

当您不想将货币存储为美分值时,您可以将 1.34 美元的货币存储为这样的对象:

{
    major: 1,
    minor: 34,
    currency: "USD"
}

Doing any math with objects like this would not be easy and would not use commercial rounding rules. But you shouldn't do any business logic on the database anyway, especially not when it's a "dumb" database like MongoDB.

用这样的对象做任何数学运算都不容易,也不会使用商业四舍五入规则。但是无论如何你都不应该在数据库上做任何业务逻辑,尤其是当它是像 MongoDB 这样的“愚蠢”数据库时。

What you should be doing is serialize/deserialize these objects from/to a Moneyclass in your application which implements the basic currency math operations respecting the rounding rules and throws an exception when you try to do an operation with different currency units ($12.34 + 14.95 = error- must convert one currency to the other currency first by providing an exchange rate).

您应该做的是将这些对象从/向Money您的应用程序中的一个类序列化/反序列化,该类实现了关于舍入规则的基本货币数学运算,并在您尝试使用不同货币单位进行操作时抛出异常($12.34 + 14.95 = error- 必须转换一个首先通过提供汇率将货币转换为另一种货币)。

回答by HNyang

If you're using Mongoose then you can use getter/setter functions in the schema definition e.g.

如果您使用的是 Mongoose,那么您可以在架构定义中使用 getter/setter 函数,例如

function getDecimalNumber(val) {    return (val/1000000); }
function setDecimalNumber(val) {    return (val*1000000); }

Applicable to a schema object such as

适用于架构对象,例如

balance: { type: Number, default: 0, get: getDecimalNumber, set: setDecimalNumber },

The number of zeroes to multiply/divide by depends on the accuracy you want.

要乘/除的零数取决于您想要的精度。

回答by heavenleft

I know this post is old but it ranks high on Google so...

我知道这篇文章很旧,但它在谷歌上排名很高,所以......

The best solution for storing financial data is using exact precision as documented by MongoDB themselves here http://docs.mongodb.org/v2.6/tutorial/model-monetary-data/#monetary-value-exact-precision.

存储财务数据的最佳解决方案是使用 MongoDB 自己在http://docs.mongodb.org/v2.6/tutorial/model-monetary-data/#monetary-value-exact-precision 中记录的精确精度。

{price: 9990, currency: "USD" }

And when you need the data just divide by 100 assuming you want 2 digit precision. The downside is that you always need to work with the same precision.

当您需要数据时,假设您想要 2 位精度,只需除以 100。缺点是您始终需要以相同的精度工作。