我有一个包含数字产品的电子商务网站(没有库存,只有报告功能)。
有时我会在客户账户余额中得到奇怪的结果:
例如,客户的余额为 30,在以 29.95 的价格购买产品后,我在管理面板中看到他的余额与预期0.050000000000001
不符。0.05
或者有时我看到520.949999999999
而不是520.95
.
为什么会这样?
站点在 PHP 上运行并通过YiiMongoDbSuite与 mongo交互
我有一个包含数字产品的电子商务网站(没有库存,只有报告功能)。
有时我会在客户账户余额中得到奇怪的结果:
例如,客户的余额为 30,在以 29.95 的价格购买产品后,我在管理面板中看到他的余额与预期0.050000000000001
不符。0.05
或者有时我看到520.949999999999
而不是520.95
.
为什么会这样?
站点在 PHP 上运行并通过YiiMongoDbSuite与 mongo交互
对于精确计算至关重要的任何类型的货币数学,不建议使用双精度或浮点数。这个问题非常详细地讨论了这个主题。一个更好的选择是用整数来跟踪这些值,其中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() 可以很好地显示,但请注意在更新文档时不要使用它,因为它返回一个字符串。