2013-05-31 7 views
0

J'ai un site de commerce électronique avec des produits numériques (pas d'inventaire, seulement des fonctionnalités de reporting).mongoDB résultats étranges après les opérations mathématiques

Et parfois j'obtenir des résultats étranges avec les clients soldes des comptes:

par exemple le client a 30 sur son solde et après l'achat d'un produit pour 29,95 je vois dans le panneau d'administration que son solde est 0.050000000000001 pas 0.05 comme prévu. Ou parfois je vois 520.949999999999 au lieu de 520.95.

Pourquoi cela se produit-il?

site fonctionne sur PHP et interagit avec mongo si YiiMongoDbSuite

+0

Pourrait-il être lié à http://stackoverflow.com/questions/588004/is-javascripts-floating-point-math-broken – Orangepill

+0

Non, s'il n'utilise pas JS pour insérer alors que ce n'est pas lié, êtes-vous formatage des nombres avant de les réenregistrer? Si non, alors c'est en fait la raison; vous devez dire à PHP comment vous voulez les sauver – Sammaye

+0

Je confondais yii avec yui. – Orangepill

Répondre

0

L'utilisation double ou flotte est pas conseillé pour toute sorte de calcul monétaire où des calculs précis sont essentiels. This question va dans les moindres détails sur le sujet. Une meilleure alternative serait de suivre ces valeurs avec des entiers, où 1 est la plus petite unité de monnaie (cent dans ce cas), et travailler à partir de là.

Selon la façon dont vous faites le calcul sur des points flottants (enregistrement des valeurs exactes, le résultat de la soustraction, ou en utilisant l'opérateur $inc), vous êtes susceptibles de se retrouver avec des résultats mitigés:

> 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 } 

Si vous utilisez des points flottants et faites les maths en PHP (ie n'utilisez pas $inc dans la requête de mise à jour), pensez à utiliser round() avec une précision d'ensemble, ce qui devrait donner des résultats similaires au premier exemple ci-dessus. number_format() est très bien pour l'affichage, mais attention à ne pas l'utiliser lors de la mise à jour du document, car il renvoie une chaîne.

Questions connexes