Opposite of Number.toExponential in JS
Asked Answered
L

5

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.

Leafy answered 13/11, 2010 at 2:31 Comment(0)
E
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.

Edulcorate answered 26/6, 2015 at 15:12 Comment(2)
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.Leafy
@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..Edulcorate
M
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.

Melancon answered 13/11, 2010 at 2:59 Comment(2)
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.Leafy
@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.Melancon
T
5

Use Number(string)

Example :

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

Return :

a = 110

Turro answered 12/7, 2015 at 9:1 Comment(2)
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.Leafy
so whats about var a=Number("9.9E-8"); ?? Its not working.. :(Gusto
E
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.

Edulcorate answered 26/6, 2015 at 15:12 Comment(2)
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.Leafy
@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..Edulcorate
L
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];
Loewi answered 13/11, 2010 at 3:45 Comment(1)
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.Leafy
A
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
Abode answered 13/11, 2010 at 4:26 Comment(1)
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.Leafy

© 2022 - 2024 — McMap. All rights reserved.