2013-05-31 31 views
0

我有一个电子商务网站与数字产品(没有库存,只有报告功能)。mongoDB数学运算后奇怪的结果

,有时我得到与客户怪异的结果账户余额:

例如客户在他的余额30和购买29.95后,我在管理面板中看到他的余额是0.050000000000001而不是0.05预期。

或有时我看到520.949999999999而不是520.95

这是怎么发生的?

网站上的PHP运行,并与蒙戈交互虽然YiiMongoDbSuite

+0

它可能与http://stackoverflow.com/questions/588004/is-javascripts-floating-point-math-broken – Orangepill

+0

相关不,如果他不使用JS插入然后是不相关的,你格式化数字,然后重新保存它们?如果不是,那么其实是原因;你需要告诉PHP你想如何保存它们 – Sammaye

+0

我很困惑yii和yui。 – Orangepill

回答

0

采用双层或漂浮,不建议用于任何形式的货币数学在需要精确的计算是至关重要的。 This question详细介绍了该主题。更好的选择是用整数跟踪这些值,其中1是货币的最小单位(在这种情况下为分),并从那里开始工作。

取决于你如何做数学题浮动点(节省精确值,相减的结果,或使用$inc运营商),你可能有不同的结果结束了:

> db.foo.insert({ _id: 'value', x: 0.05 }) 
> db.foo.insert({ _id: 'subtraction', x: 30 - 29.95 }) 
> db.foo.insert({ _id: 'decrement', x: 30 }) 
> db.foo.update({ _id: 'decrement' }, { $inc: { x: -29.95 }}) 
> db.foo.find() 
{ "_id" : "value", "x" : 0.05 } 
{ "_id" : "subtraction", "x" : 0.05000000000000071 } 
{ "_id" : "decrement", "x" : 0.05000000000000071 } 

如果你已经开始使用浮点数并在PHP中进行数学运算(即在更新查询中不使用$inc),请考虑使用round()以设置精度,这应该会产生类似于上面第一个示例的结果。 number_format()可以显示,但在更新文档时请注意不要使用它,因为它返回一个字符串。