I would like to understand how aggregation $sum
accumulator works for big numbers and small numbers. In this example, I’m using neg-big
, neg-bigger
, pos-big
and pos-bigger
for doubles that are big enough to lose precision, a very small number small
and a standard double number
.
test> db.test.insertMany(
[
{ _id: 'number', val: 41.13 },
{ _id: 'small', val: 5e-324 },
{ _id: 'pos-big', val: 9223372036854776000 },
{ _id: 'neg-big', val: -9223372036854776000 },
{ _id: 'pos-bigger', val: 9223372036854778000 },
{ _id: 'neg-bigger', val: -9223372036854778000 }
]
)
Below shows $sort
responses for applying ascending sort and descending sort on _id
.
test> db.test.aggregate([ {$sort: {_id: 1} } ])
[
{ _id: 'neg-big', val: -9223372036854776000 },
{ _id: 'neg-bigger', val: -9223372036854778000 },
{ _id: 'number', val: 41.13 },
{ _id: 'pos-big', val: 9223372036854776000 },
{ _id: 'pos-bigger', val: 9223372036854778000 },
{ _id: 'small', val: 5e-324 }
]
test> db.test.aggregate([{$sort: {_id: -1} } ])
[
{ _id: 'small', val: 5e-324 },
{ _id: 'pos-bigger', val: 9223372036854778000 },
{ _id: 'pos-big', val: 9223372036854776000 },
{ _id: 'number', val: 41.13 },
{ _id: 'neg-bigger', val: -9223372036854778000 },
{ _id: 'neg-big', val: -9223372036854776000 }
]
When I apply $group
’s $sum
accumulator after ascending sort, it returns 41.13000000000011
.
test> db.test.aggregate([ {$sort: {_id: 1} }, { $group: { _id: null, total: { $sum: "$val" } } } ])
[ { _id: null, total: 41.13000000000011 } ]
While if I apply it after descending sort, it returns 0
.
test> db.test.aggregate([{$sort: {_id: -1} }, { $group: { _id: null, total: { $sum: "$val" } } } ])
[ { _id: null, total: 0 } ]
How does ascending sort sums up to41.13000000000011
. I think number
contributes to 41.13
but where does the rest of it comes from? I would understand if there is lost precision resulting in such as 41.1300000000001
, but double 11
at the end is mystery to me.
Also how does the descending sort result sums up to 0
?
I would like to understand them so I know how I could handle large numbers.