Javascript parsing int64
Asked Answered
D

5

27

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.

Determined answered 18/3, 2011 at 14:27 Comment(1)
Number.MAX_SAFE_INTEGER ... Number.MIN_SAFE_INTEGERToot
H
45

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.

EDIT 2023/11 the BigInt class has been supported in all mainstream JS engines since late 2020.

Hom answered 18/3, 2011 at 14:34 Comment(6)
Thank you. He has a lot of useful functions which I can see are going to help me for some time to come. CheersDetermined
you're welcome! The fact that all numbers in JS are actually doubles is fundamental to the language, but apparently not well known.Hom
@Hom If the largest positive whole number is 2^53, how is it that parseInt() can return bigger than that?Consuetudinary
@Consuetudinary for larger numbers you'll get an approximation, with missing bits in the least significant positions.Hom
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.Toot
From functions support perspective, bn.js much more than BigInteger - actually many packages used in browserify, such as crypto are using it.Singleminded
C
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";
}
Chrisom answered 18/3, 2011 at 14:36 Comment(4)
@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...Chrisom
@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.Winy
@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? :)Winy
+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.Dominickdominie
W
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.

Winy answered 18/3, 2011 at 14:45 Comment(0)
L
-2

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

Lette answered 18/3, 2011 at 14:31 Comment(0)
C
-4

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

Cocteau answered 18/3, 2011 at 14:29 Comment(5)
-1 Does not work in Chrome: number("9223372036854775808") and NUMBER("9223372036854775808") both fail.Winy
@x3ro - Check this article, It says Chrome is also supported - w3schools.com/jsref/jsref_Number.aspCocteau
@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 newWiny
@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.Cocteau
@Sachin Shanbhag: Ah okay, my bad. Anyhow, new Number() and Number() seem to be identical.Winy

© 2022 - 2024 — McMap. All rights reserved.