2013-03-22 101 views
0

的MapReduce的我寫的MongoDB的映射縮減,但結果有一些問題爲什麼計算結果是不正確的MongoDB中

日期:

mongos> db.perGoods.find()

{ "_id" : ObjectId("514bf6428f43a9fee9cef526"), "id" : 1, "goods_id" : "1234", "keywords" : [ { "keyword" : "lianyiqun", "price" : 3.52 }, { "keyword" : "nvzhuang",  "price" : 4.27 }, { "keyword" : "chunkuan",  "price" : 3.12 }, { "keyword" : "chaoliu", "price" : 8.32 }, { "keyword" : "duanzhuang", "price" : 4.92 } ] } 
{ "_id" : ObjectId("514bf65d8f43a9fee9cef527"), "id" : 2, "goods_id" : "5678", "keywords" : [ { "keyword" : "lianyiqun", "price" : 9.26 }, { "keyword" : "nvzhuang",  "price" : 4.52 } ] } 
{ "_id" : ObjectId("514bf6768f43a9fee9cef528"), "id" : 3, "goods_id" : "5612", "keywords" : [ { "keyword" : "lianyiqun", "price" : 7.42 }, { "keyword" : "nvzhuang",  "price" : 6.52 } ] } 
{ "_id" : ObjectId("514bf6968f43a9fee9cef529"), "id" : 4, "goods_id" : "9612", "keywords" : [ { "keyword" : "lianyiqun", "price" : 3.12 }, { "keyword" : "nvzhuang",  "price" : 6.57 }, { "keyword" : "chunzhuang", "price" : 5.55 } ] } 

在地圖功能:

mongos> var mapFunction = function() { 
...      for (var index = 0; index < this.keywords.length; index++) { 
...       var key = this.goods_id; 
...       var value = { 
...           count: 1, 
...           price: this.keywords[index].price 
...          }; 
...       emit(key, value); 
...      } 
...      }; 

的降低功能:

mongos> var reduceFunction = function(key, priceCountObjects) { 
...       reducedValue = { count: 0, sumprice: 0 }; 
... 
...       for (var index = 0; index < priceCountObjects.length; index++) { 
...        reducedValue.count += priceCountObjects[index].count; 
...        reducedValue.sumprice += priceCountObjects[index].price; 
...       } 
... 
...       return reducedValue; 
...      }; 

代碼:

mongos> db.perGoods.mapReduce(
...      mapFunction, 
...      reduceFunction, 
...      { out: "map_reduce_test" } 
...     ) 
{ 
    "result" : "map_reduce_test", 
    "timeMillis" : 5, 
    "counts" : { 
     "input" : 4, 
     "emit" : 12, 
     "reduce" : 4, 
     "output" : 4 
    }, 
    "ok" : 1, 
} 

結果:

mongos> db.map_reduce_test.find() 
{ "_id" : "1234", "value" : { "count" : 5, "sumprice" : 24.15 } } 
{ "_id" : "5612", "value" : { "count" : 2, "sumprice" : 13.94 } } 
{ "_id" : "5678", "value" : { "count" : 2, "sumprice" : 13.78 } } 
{ "_id" : "9612", "value" : { "count" : 3, "sumprice" : 15.240000000000002 } } 
mongos> 

爲什麼最後的結果是15.240000000000002?

+1

結果是否錯誤? '3.12 + 6.57 + 5.55 == 15.240000000000002 // true'。或者這個問題是爲什麼它有很多小數位? – tjameson 2013-03-22 07:02:12

+0

相關:http://stackoverflow.com/questions/11150741/javascript-add-operation-returns-bad-result/11150751#11150751 – tjameson 2013-03-22 07:09:13

回答

0

由於MongoDB中的map/reduce基於JavaScript,因此它使用JavaScript的number arithmetic,這基本上是雙精度IEEE 754 floating point arithmetic

浮點數(基本上,詳情請參閱維基百科文章)存儲爲

mantissa * base^exponent 

在這種情況下,鹼是2(底座10個浮點數被稱爲decimal),和一些數字,包括有理數,如果這些值的精度有限,則無法完全用這種格式表示。

就目前來看,最好的辦法可能是在操作結束時進行四捨五入。不幸的是,並不是所有的貨幣都有兩位小數所以國際化有可能成爲一種痛苦,而且還是該舍入成爲顯著的危險 - 可以肯定,要確保你知道What Every Computer Scientist Should Know About Floating-Point Arithmetic

您也可以vote for this feature in 10gen's Jira

相關問題