9

I need to get the value of an extremely large number in JavaScript in non-exponential form. Number.toFixed simply returns it in exponential form as a string, which is worse than what I had.

This is what Number.toFixed returns:

>>> x = 1e+31
1e+31
>>> x.toFixed()
"1e+31"

Number.toPrecision also does not work:

>>> x = 1e+31
1e+31
>>> x.toPrecision( 21 )
"9.99999999999999963590e+30"

What I would like is:

>>> x = 1e+31
1e+31
>>> x.toNotExponential()
"10000000000000000000000000000000"

I could write my own parser but I would rather use a native JS method if one exists.

Oz.
  • 5,299
  • 2
  • 23
  • 30

5 Answers5

5

You can use toPrecision with a parameter specifying how many digits you want to display:

x.toPrecision(31)

However, among the browsers I tested, the above code only works on Firefox. According to the ECMAScript specification, the valid range for toPrecision is 1 to 21, and both IE and Chrome throw a RangeError accordingly. This is due to the fact that the floating-point representation used in JavaScript is incapable of actually representing numbers to 31 digits of precision.

casablanca
  • 69,683
  • 7
  • 133
  • 150
  • 1
    I'm fine with it not being an actual number when I get it (it is for display purposes) but toPrecision doesn't work either for numbers larger than 1e+21. In this particular case I get "9.99999999999999963590e+30". I will update the question accordingly. – Oz. Nov 13 '10 at 03:37
  • @Oz: Yes, that's what I mentioned. I don't think there is any other built-in way to get strings for such large numbers. – casablanca Nov 13 '10 at 03:38
4

Use Number(string)

Example :

var a = Number("1.1e+2");

Return :

a = 110

whoami - fakeFaceTrueSoul
  • 17,086
  • 6
  • 32
  • 46
  • That's the opposite of what I'm going for. There are lots of ways to go from a string to a number, but I'm looking for going from an extremely large number to string without using exponentiation. – Oz. Jul 14 '15 at 00:09
  • so whats about var a=Number("9.9E-8"); ?? Its not working.. :( – Soumyadip Das Dec 08 '16 at 10:42
2

The answer is there's no such built-in function. I've searched high and low. Here's the RegExp I use to split the number into sign, coefficient (digits before decimal point), fractional part (digits after decimal point) and exponent:

/^([+-])?(\d+)\.?(\d*)[eE]([+-]?\d+)$/

"Roll your own" is the answer, which you already did.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
Gene Pavlovsky
  • 1,515
  • 17
  • 14
  • I have long since forgotten what I did to solve this, but you are correct that there is no built-in method for doing this. – Oz. Jun 29 '15 at 17:50
  • @Oz Hey thanks man, finally I can comment on questions! That's a big pain with the built-in printing methods, something like a "printf" would surely be nice. I'm working on a custom NumberFormatter class now.. – Gene Pavlovsky Jun 29 '15 at 20:09
1

It's possible to expand JavaScript's exponential output using string functions. Admittedly, what I came up is somewhat cryptic, but it works if the exponent after the e is positive:

var originalNumber = 1e+31;
var splitNumber = originalNumber.toString().split('e');

var result;
if(splitNumber[1]) {
    var regexMatch = splitNumber[0].match(/^([^.]+)\.?(.*)$/);
    result =
        /* integer part */ regexMatch[1] +
        /* fractional part */ regexMatch[2] +
        /* trailing zeros */ Array(splitNumber[1] - regexMatch[2].length + 1).join('0');
} else result = splitNumber[0];
PleaseStand
  • 31,641
  • 6
  • 68
  • 95
  • I am currently using my own conversion function that splits the toString version of the number, similar to yours though without the empty Array joining. However I am looking for a native JS function to do this for me. – Oz. Nov 13 '10 at 03:57
1

"10000000000000000000000000000000"?

Hard to believe that anybody would rather look at that than 1.0e+31,

or in html: 1031. But here's one way, much of it is for negative exponents(fractions):

function longnumberstring(n){
    var str, str2= '', data= n.toExponential().replace('.','').split(/e/i);
    str= data[0], mag= Number(data[1]);
    if(mag>=0 && str.length> mag){
        mag+=1;
        return str.substring(0, mag)+'.'+str.substring(mag);            
    }
    if(mag<0){
        while(++mag) str2+= '0';
        return '0.'+str2+str;
    }
    mag= (mag-str.length)+1;
    while(mag> str2.length){
        str2+= '0';
    }
    return str+str2;
}



input: 1e+30
longnumberstring: 1000000000000000000000000000000
to Number: 1e+30
input: 1.456789123456e-30
longnumberstring: 0.000000000000000000000000000001456789123456
to Number: 1.456789123456e-30
input: 1.456789123456e+30
longnumberstring: 1456789123456000000000000000000
to Number: 1.456789123456e+30
input: 1e+80 longnumberstring: 100000000000000000000000000000000000000000000000000000000000000000000000000000000
to Number: 1e+80
kennebec
  • 102,654
  • 32
  • 106
  • 127
  • It is to be displayed as a dollar value and $1e+31 doesn't read well. The value is so high because it is user input and users are crazy. Thanks for the function, but I already have a function I wrote to do it, I was wondering if there was a built in one. – Oz. Nov 13 '10 at 18:44