25

How can I convert a long integer (as a string) to a numerical format in Javascript without javascript rounding it?

var ThisInt = '9223372036854775808'
alert(ThisInt+'\r' +parseFloat(ThisInt).toString()+'\r' +parseInt(ThisInt).toString());

I need to perform an addition on it before casting it back as a string & would prefer not to have to slice it two if at all possible.

Oppdal
  • 591
  • 3
  • 7
  • 15
  • [Number.MAX_SAFE_INTEGER](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER) ... [Number.MIN_SAFE_INTEGER](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER) – Andrew Feb 23 '18 at 04:29

5 Answers5

40

All Numbers in Javascript are 64 bit "double" precision IEE754 floating point.

The largest positive whole number that can therefore be accurately represented is 2^53 - 1. The remaining bits are reserved for the exponent.

Your number is exactly 1024 times larger than that, so loses 3 decimal digits of precision. It simply cannot be represented any more accurately.

In ES6 one can use Number.isSafeInteger( # ) to test a number to see if its within the safe range:

var ThisInt = '9223372036854775808'; 
console.log( Number.isSafeInteger( parseInt( ThisInt ) ) );

There is also a BigInteger library available which should be able to help, though, and avoid you having to do all the string and bit twiddling yourself.

EDIT 2018/12 there's now a native BigInt class (and new literal syntax) landed in Chrome and NodeJS.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • Thank you. He has a lot of useful functions which I can see are going to help me for some time to come. Cheers – Oppdal Mar 18 '11 at 15:18
  • you're welcome! The fact that all numbers in JS are actually doubles is fundamental to the language, but apparently not well known. – Alnitak Mar 18 '11 at 15:19
  • @Alnitak If the largest positive whole number is 2^53, how is it that parseInt() can return bigger than that? – Alex Dec 29 '17 at 07:09
  • 1
    @Alex for larger numbers you'll get an approximation, with missing bits in the least significant positions. – Alnitak Dec 30 '17 at 08:13
  • 1
    In Firefox Quantum 58.0.2, running `javascript:(alert(Math.pow(2, 53)))` returns `9007199254740992`, and running `javascript:(alert(-Math.pow(2, 53)))` returns `-9007199254740992`. If I add 1 to the max or subtract 1 from the min, it returns those same numbers. – Andrew Feb 23 '18 at 04:24
  • From functions support perspective, **bn.js** much more than **BigInteger** - actually many packages used in browserify, such as **crypto** are using it. – tibetty Dec 14 '18 at 06:07
2

With a little help from recursion, you can directly increment your decimal string, be it representing a 64 bit number or more...

/**
 * Increment a decimal by 1
 *
 * @param {String} n The decimal string
 * @return The incremented value
 */
function increment(n) {
    var lastChar = parseInt(n.charAt(n.length - 1)),
        firstPart = n.substr(0, n.length - 1);

    return lastChar < 9
        ? firstPart + (lastChar + 1)
        : firstPart
            ? increment(firstPart) + "0"
            : "10";
}
Ates Goral
  • 137,716
  • 26
  • 137
  • 190
  • 1
    @x3ro: Why? It's all in getting used to proper indentation. Terse syntax that's following a convention is often better than verbose code that takes ages to mentally parse. I think you are blindly applying conventional wisdom (that "terse is bad") without considering the usage... – Ates Goral Mar 28 '11 at 08:47
  • 1
    @Ates Goral: No, not really (to the applying conventional wisdom). I see why it is done like this, however I think that it decreases the readability of your code significantly, and thats why I dislike it. But maybe I'm a bit damaged too, because I had to debug code with like 10 nested ternary operators, and it wasn't that much fun. – fresskoma Mar 28 '11 at 10:06
  • @Ates Goral: Yeah, true. However, imagine you need a quick change in such a piece of code. Probably you would rather add another ternary than rewrite it, wouldn't you? :) – fresskoma Apr 01 '11 at 03:59
  • +1 for a functional suggestion. I don't like needless complexity in general, and this *could* be argued as being that, but that doesn't mean it's a bad solution. It just means that if I don't want to allow it, I'll say so in our coding standards. That is, afterall, what they're for. – Jaxidian Apr 21 '11 at 16:47
1

You cannot do this with standard Javascript. But as always, there is a nifty little library to help us out, in this case BigInt.js, which will let you use arbitrary-precision integers.

fresskoma
  • 25,481
  • 10
  • 85
  • 128
-2

Have you tried using the Number class?
var num = new Number(parseFloat(ThisInt))

Christopher Armstrong
  • 7,907
  • 2
  • 26
  • 28
-4

Just use Number(ThisInt) for this instead of Int or float

Sachin Shanbhag
  • 54,530
  • 11
  • 89
  • 103
  • 1
    -1 Does not work in Chrome: `number("9223372036854775808")` and `NUMBER("9223372036854775808")` both fail. – fresskoma Mar 18 '11 at 14:31
  • 1
    @x3ro - Check this article, It says Chrome is also supported - http://www.w3schools.com/jsref/jsref_Number.asp – Sachin Shanbhag Mar 18 '11 at 14:32
  • @Sachin Shanbhag: Yep, but the way you answered one would suspect Number to be a function rather than an object of which you need to create an instance with `new` – fresskoma Mar 18 '11 at 14:34
  • @x3ro - Hey, no I did not mean to create instance of object tough. Check the article, Number() function can be used directly without having to create instance. This is indeed a global function. – Sachin Shanbhag Mar 18 '11 at 14:35
  • 2
    @Sachin Shanbhag: Ah okay, my bad. Anyhow, `new Number()` and `Number()` seem to be identical. – fresskoma Mar 18 '11 at 14:40