# MongoDB's NumberLong only 54 bit signed?

Is really a MongoDB's NumberLong really 64 bit signed integer really 64 bit?

MongoDB's NumberLong is stated to become a 64 bit signed integer, that ought to mean we are able to have fun with -2^63 <= x <= 2^63-1, where x is really a NumberLong. However, adding 1 or subtracting 1 from the NumberLong(x) doesn't return the expected value for x <= -2^54 or x >= 2^54, but correct values are came back for -2^53 <= x <= 2^53.
Trustworthy NumberLong amounts because of this appear to become 54 bit signed integers.

Why?
Shall We Be Held doing someting wrong?

Sample in the mongo spend:

``````> NumberLong( Math.pow(2,54) )
NumberLong("18014398509481984")    // Expected
> NumberLong( Math.pow(2,54)-1 )
NumberLong("18014398509481984")    // **NOT** Expected
> NumberLong( -Math.pow(2,54) )
NumberLong("-18014398509481984")   // Expected
> NumberLong( -Math.pow(2,54)+1 )
NumberLong("-18014398509481984")   // **NOT** Expected

> NumberLong( Math.pow(2,53) )
NumberLong("9007199254740992")     // Expected
> NumberLong( Math.pow(2,53)-1 )
NumberLong("9007199254740991")     // Expected
> NumberLong( -Math.pow(2,53) )
NumberLong("-9007199254740992")    // Expected
> NumberLong( -Math.pow(2,53)+1 )
NumberLong("-9007199254740991")    // Expected
``````

Using MongoDB 2..

`Math.pow` probably works on `double`s. The integers are pushed to floats, and also at 2^54, double precision amounts lose resolution in the 1's place. The details are lost at that time you are converting to integer types.

would you get comparable results using left change `<<` or repeated multiplication?

Wow, this really is puzzling. Clearly there's some kind of rounding error happening here.

``````> NumberLong("18014398509481984")-NumberLong("1");
18014398509481984

> NumberLong("18014398509481984")-NumberLong("2");
18014398509481982

> NumberLong("18014398509481984")+NumberLong("1");
18014398509481984

> NumberLong("18014398509481984")+NumberLong("2");
18014398509481984

> NumberLong("18014398509481984")+NumberLong("3");
18014398509481988
``````

This really is most likely a problem using the JavaScript engine the spend runs in, instead of MongoDB itself. Look at this, for instance--`\$inc` works fine:

``````> db.test.insert({twoTo54:NumberLong("18014398509481984")});
> db.test.update({},{\$inc:{twoTo54:NumberLong("1")}});
> db.test.find();
{ "_id" : ObjectId("4f204847756aa806028abce1"), "twoTo54" : NumberLong("18014398509481985") }
> db.test.update({},{\$inc:{twoTo54:NumberLong("1")}});
> db.test.find();
{ "_id" : ObjectId("4f204847756aa806028abce1"), "twoTo54" : NumberLong("18014398509481986") }
> db.test.update({},{\$inc:{twoTo54:NumberLong("1")}});
> db.test.find();
{ "_id" : ObjectId("4f204847756aa806028abce1"), "twoTo54" : NumberLong("18014398509481987") }
``````

You need to be careful, though. If you are using only a normal literal `1`, it'll convert the kind to some Number, which in turn breaks the `\$inc`:

``````> db.test.update({},{\$inc:{twoTo54:1}});
> db.test.find();
{ "_id" : ObjectId("4f204847756aa806028abce1"), "twoTo54" : 18014398509481988 }
> db.test.update({},{\$inc:{twoTo54:1}});
> db.test.find();
{ "_id" : ObjectId("4f204847756aa806028abce1"), "twoTo54" : 18014398509481988 }
``````

And even when you return to `\$inc` with `NumberLong("1")`, will still be damaged:

``````> db.test.update({},{\$inc:{twoTo54:NumberLong("1")}});
> db.test.find();
{ "_id" : ObjectId("4f204847756aa806028abce1"), "twoTo54" : 18014398509481988 }
``````

Certainly good to bear in mind.