2012-03-29 16 views
1

私はMongoDBを初め、いくつかの基本を試していますが、これは私を驚かせました。私はいくつかのコアコンセプトを誤解していると思っていますが、誰が私にここで何が起こっているのか教えていただけますか?グループ()でMongoDBの二重丸め誤差

公式のMongoDB C#ドライブを使用して、10,0000個のこれらのドキュメントを「lots」というdbコレクションに挿入しました。

  // Insert some test data 
     const double price = 29.99; 
     var bsonDoc = new BsonDocument { 
      {"glossary", new BsonDocument { 
        {"title", "example glossary"}, 
        {"GlossDiv", new BsonDocument { 
         {"title", "S"}, 
         {"price", new BsonDouble(price)}, 
       ... 
       /* full doc chunk removed here for brevity */ 
       ... 
      }; 
      ... 
         const int numObjects = 10000; 
     for (int i = 0; i < numObjects; i++) 
      col.Insert(new BsonDocument(bsonDoc)); 

      ... 

私はC#ドライバで何を見ているのか信じなかったので、これをシェルで試しましたが、結果は同じです。

db.lots.group({キー:{ "glossary.GlossDiv.title":真}、低減:機能(OBJ、アウト){out.total + = obj.glossary.GlossDiv.price;}初期:{合計:0}}) [{ "glossary.GlossDiv.title": "S"、 "合計":299899.99999995757}]私が間違っているが、場合

が私を修正してはいけません29.99 * 10000 == ?

答えて

3

私が間違っていても正しいはずですが、29.99 * 10000 == 299900ではありませんか?

データに29.99が含まれていませんでした。ここを見て:29.99から最も近いあるdouble値に等しいpriceを設定

const double price = 29.99; 

を。それはではなく、 29.99です。正確には、値は29.989999999999998436805981327779591083526611328125です。

これはMongoと接するだけです。バイナリ浮動小数点を使うことが基本です。 Mongoがdecimalをサポートしている場合は、代わりに任意の財務値に使用する必要があります。 を参照してください。BsonDecimalのようなものがあります。これを行うことができない場合は、代わりに縮尺の整数として値を保存することをおすすめします。ドルの代わりにセントの数を格納する。

詳細は、binary floating pointおよびdecimal floating pointに関する記事をご覧ください。

+0

いいえ。私はMongoが小数をサポートしているとは思わない。私はそれが何か基本的なものだと思った。私はC#でダブルを計算すればいいので、期待していなかったことを見ないと驚いた。私はすでに読んでいたことのいくつかのために整数を使うことを検討していましたが、Mongoが小数点を含む数字を受け入れたように見えたのはなぜか分かりました。ありがとうジョン! – cirrus