137

JavaScript converts a large INT to scientific notation when the number becomes large. How can I prevent this from happening?

  • 1
    Do you want 1E21 to display as '1000000000000000000000'? Are you concerned with how the number is displayed, or how it is stored? – outis Nov 6 '09 at 6:19
  • 2
    i am concerned about how it is displayed: I have a document.write(myvariable) command – chris Nov 6 '09 at 6:20
  • 1
    i need the number as part of a URL – chris Nov 6 '09 at 21:43
  • 1
    @outis: Human users are not the only ones who want to read numbers. It seems D3 will throw an exception when encountering a translate transformation that contains coordinates in scientific notation. – O. R. Mapper Sep 7 '17 at 9:05
  • 1
    There is still a use for this when you are dealing with numbers up to a certain size. Scientific notation will be hard to read for users who don't know scientific notation too after all. – hippietrail Sep 15 '17 at 3:08

21 Answers 21

94

There's Number.toFixed, but it uses scientific notation if the number is >= 1e21 and has a maximum precision of 20. Other than that, you can roll your own, but it will be messy.

function toFixed(x) {
  if (Math.abs(x) < 1.0) {
    var e = parseInt(x.toString().split('e-')[1]);
    if (e) {
        x *= Math.pow(10,e-1);
        x = '0.' + (new Array(e)).join('0') + x.toString().substring(2);
    }
  } else {
    var e = parseInt(x.toString().split('+')[1]);
    if (e > 20) {
        e -= 20;
        x /= Math.pow(10,e);
        x += (new Array(e+1)).join('0');
    }
  }
  return x;
}

Above uses cheap-'n'-easy string repetition ((new Array(n+1)).join(str)). You could define String.prototype.repeat using Russian Peasant Multiplication and use that instead.

This answer should only be applied to the context of the question: displaying a large number without using scientific notation. For anything else, you should use a BigInt library, such as BigNumber, Leemon's BigInt, or BigInteger. Going forward, a proposed BigInt (note: not Leemon's) should be supported natively (Chrome has support, and it's being worked on for Firefox).

  • 4
    @Shane: This Q&A is about displaying floating point numbers as base-10 integers and doesn't address numbers that can't be represented in a floating point format (which will arise when converting to base 10). You need a JS bigint library, as is mentioned in the final line. – outis Aug 11 '11 at 1:05
  • 2
    This doesn't work on negative numbers; e.g. -1e56. – Peter Olson Mar 23 '12 at 16:54
  • 1
    @PeterOlson: look like I left out a Math.abs. Thanks for the heads-up. – outis Mar 23 '12 at 17:38
  • 1
    toFixed(Number.MAX_VALUE) == Number.MAX_VALUE should return true then, but it doesn't... – manonthemat Jan 17 '17 at 22:02
  • 3
    Actually this code as it is does not work for very small negative numbers: toFixed( -1E-20 ) -> "0.0000000000000000000.09999999999999999" – davidthings Jun 15 '17 at 0:37
18

For small number, and you know how many decimals you want, you can use toFixed and then use a regexp to remove the trailing zeros.

Number(1e-7).toFixed(8).replace(/\.?0+$/,"") //0.000
15

one more possible solution:

function toFix(i){
 var str='';
 do{
   let a = i%10;
   i=Math.trunc(i/10);
   str = a+str;
 }while(i>0)
 return str;
}
10

I know this is an older question, but shows recently active. MDN toLocaleString

const myNumb = 1000000000000000000000;
console.log( myNumb ); // 1e+21
console.log( myNumb.toLocaleString() ); // "1,000,000,000,000,000,000,000"
console.log( myNumb.toLocaleString('fullwide', {useGrouping:false}) ); // "1000000000000000000000"

you can use options to format the output.

Note:

Number.toLocaleString() rounds after 16 decimal places, so that...

const myNumb = 586084736227728377283728272309128120398;
console.log( myNumb.toLocaleString('fullwide', { useGrouping: false }) );

...returns...

586084736227728400000000000000000000000

This is perhaps undesirable if accuracy is important in the intended result.

8

Here is my short variant of Number.prototype.toFixed method that works with any number:

Number.prototype.toFixedSpecial = function(n) {
    var str = this.toFixed(n);
    if (str.indexOf('e+') < 0)
        return str;

    // if number is in scientific notation, pick (b)ase and (p)ower
    return str.replace('.', '').split('e+').reduce(function(p, b) {
        return p + Array(b - p.length + 2).join(0);
    }) + '.' + Array(n + 1).join(0);
};

1e21.toFixedSpecial(2);       // "1000000000000000000000.00"
2.1e24.toFixedSpecial(0);     // "2100000000000000000000000"
1234567..toFixedSpecial(1);   // "1234567.0"
1234567.89.toFixedSpecial(3); // "1234567.890"
6

The following solution bypasses the automatic exponentional formatting for very big and very small numbers. This is outis's solution with a bugfix: It was not working for very small negative numbers.

function numberToString(num)
{
    let numStr = String(num);

    if (Math.abs(num) < 1.0)
    {
        let e = parseInt(num.toString().split('e-')[1]);
        if (e)
        {
            let negative = num < 0;
            if (negative) num *= -1
            num *= Math.pow(10, e - 1);
            numStr = '0.' + (new Array(e)).join('0') + num.toString().substring(2);
            if (negative) numStr = "-" + numStr;
        }
    }
    else
    {
        let e = parseInt(num.toString().split('+')[1]);
        if (e > 20)
        {
            e -= 20;
            num /= Math.pow(10, e);
            numStr = num.toString() + (new Array(e + 1)).join('0');
        }
    }

    return numStr;
}

// testing ...
console.log(numberToString(+0.0000000000000000001));
console.log(numberToString(-0.0000000000000000001));
console.log(numberToString(+314564649798762418795));
console.log(numberToString(-314564649798762418795));

3

This is what I ended up using to take the value from an input, expanding numbers less than 17digits and converting Exponential numbers to x10y

// e.g.
//  niceNumber("1.24e+4")   becomes 
// 1.24x10 to the power of 4 [displayed in Superscript]

function niceNumber(num) {
  try{
        var sOut = num.toString();
      if ( sOut.length >=17 || sOut.indexOf("e") > 0){
      sOut=parseFloat(num).toPrecision(5)+"";
      sOut = sOut.replace("e","x10<sup>")+"</sup>";
      }
      return sOut;

  }
  catch ( e) {
      return num;
  }
}
2

You can loop over the number and achieve the rounding

// functionality to replace char at given index

String.prototype.replaceAt=function(index, character) {
    return this.substr(0, index) + character + this.substr(index+character.length);
}

// looping over the number starts

var str = "123456789123456799.55";
var arr = str.split('.');
str = arr[0];
i = (str.length-1);
if(arr[1].length && Math.round(arr[1]/100)){
  while(i>0){
    var intVal = parseInt(str.charAt(i));

   if(intVal == 9){
      str = str.replaceAt(i,'0');
      console.log(1,str)
   }else{
      str = str.replaceAt(i,(intVal+1).toString()); 
      console.log(2,i,(intVal+1).toString(),str)
      break;
   }
   i--;
 }
}
2

I tried working with the string form rather than the number and this seemed to work. I have only tested this on Chrome but it should be universal:

function removeExponent(s) {
    var ie = s.indexOf('e');
    if (ie != -1) {
        if (s.charAt(ie + 1) == '-') {
            // negative exponent, prepend with .0s
            var n = s.substr(ie + 2).match(/[0-9]+/);
            s = s.substr(2, ie - 2); // remove the leading '0.' and exponent chars
            for (var i = 0; i < n; i++) {
                s = '0' + s;
            }
            s = '.' + s;
        } else {
            // positive exponent, postpend with 0s
            var n = s.substr(ie + 1).match(/[0-9]+/);
            s = s.substr(0, ie); // strip off exponent chars            
            for (var i = 0; i < n; i++) {
                s += '0';
            }       
        }
    }
    return s;
}
2

I think there may be several similar answers, but here's a thing I came up with

// If you're gonna tell me not to use 'with' I understand, just,
// it has no other purpose, ;( andthe code actually looks neater
// 'with' it but I will edit the answer if anyone insists
var commas = false;

function digit(number1, index1, base1) {
    with (Math) {
        return floor(number1/pow(base1, index1))%base1;
    }
}

function digits(number1, base1) {
    with (Math) {
        o = "";
        l = floor(log10(number1)/log10(base1));
        for (var index1 = 0; index1 < l+1; index1++) {
            o = digit(number1, index1, base1) + o;
            if (commas && i%3==2 && i<l) {
                o = "," + o;
            }
        }
        return o;
    }
}

// Test - this is the limit of accurate digits I think
console.log(1234567890123450);

Note: this is only as accurate as the javascript math functions and has problems when using log instead of log10 on the line before the for loop; it will write 1000 in base-10 as 000 so I changed it to log10 because people will mostly be using base-10 anyways.

This may not be a very accurate solution but I'm proud to say it can successfully translate numbers across bases and comes with an option for commas!

1

Use .toPrecision, .toFixed, etc. You can count the number of digits in your number by converting it to a string with .toString then looking at its .length.

  • what if I don't know how many digits my integer is? – chris Nov 6 '09 at 5:57
  • for some reason, toPrecision doesn't work. if you try: window.examplenum = 1352356324623461346, and then say alert(window.examplenum.toPrecision(20)), it doesn't pop up an alert – chris Nov 6 '09 at 6:05
  • actually it pops up sometimes showing scientific notation, and other times it doesn't pop up at all. what am i doing wrong? – chris Nov 6 '09 at 6:06
  • 16
    Neither of the suggestion methods work for large (or small) numbers. (2e64).toString() will return "2e+64", so .length is useless. – CoDEmanX Nov 5 '14 at 23:05
1

Your question:

number :0x68656c6c6f206f72656f display:4.9299704811152646e+23

you can use this : https://github.com/MikeMcl/bignumber.js

A JavaScript library for arbitrary-precision decimal and non-decimal arithmetic.

like this :

let ten =new BigNumber('0x68656c6c6f206f72656f',16); console.log(ten.toString(10)); display:492997048111526447310191

1

I know it's many years later, but I had been working on a similar issue recently and I wanted to post my solution. The currently accepted answer pads out the exponent part with 0's, and mine attempts to find the exact answer, although in general it isn't perfectly accurate for very large numbers because of JS's limit in floating point precision.

This does work for Math.pow(2, 100), returning the correct value of 1267650600228229401496703205376.

function toFixed(x) {
  var result = '';
  var xStr = x.toString(10);
  var digitCount = xStr.indexOf('e') === -1 ? xStr.length : (parseInt(xStr.substr(xStr.indexOf('e') + 1)) + 1);
  
  for (var i = 1; i <= digitCount; i++) {
    var mod = (x % Math.pow(10, i)).toString(10);
    var exponent = (mod.indexOf('e') === -1) ? 0 : parseInt(mod.substr(mod.indexOf('e')+1));
    if ((exponent === 0 && mod.length !== i) || (exponent > 0 && exponent !== i-1)) {
      result = '0' + result;
    }
    else {
      result = mod.charAt(0) + result;
    }
  }
  return result;
}

console.log(toFixed(Math.pow(2,100))); // 1267650600228229401496703205376

1

Use this function:

function toNonExponential(value) {
    // if value is not a number try to convert it to number
    if (typeof value !== "number") {
        value = parseFloat(value);

        // after convert, if value is not a number return empty string
        if (isNaN(value)) {
            return "";
        }
    }

    var sign;
    var e;

    // if value is negative, save "-" in sign variable and absolute the value
    if (value < 0) {
        sign = "-";
        value = Math.abs(value);
    }
    else {
        sign = "";
    }

    // if value is between 0 and 1
    if (value < 1.0) {
        // get e value
        e = parseInt(value.toString().split('e-')[1]);

        // if value is exponential convert it to non exponential
        if (e) {
            value *= Math.pow(10, e - 1);
            value = '0.' + (new Array(e)).join('0') + value.toString().substring(2);
        }
    }
    else {
        // get e value
        e = parseInt(value.toString().split('e+')[1]);

        // if value is exponential convert it to non exponential
        if (e) {
            value /= Math.pow(10, e);
            value += (new Array(e + 1)).join('0');
        }
    }

    // if value has negative sign, add to it
    return sign + value;
}
0

If you are just doing it for display, you can build an array from the digits before they're rounded.

var num = Math.pow(2, 100);
var reconstruct = [];
while(num > 0) {
    reconstruct.unshift(num % 10);
    num = Math.floor(num / 10);
}
console.log(reconstruct.join(''));
  • This will return the right answer, but will take so much time and might end up for the execution to time out. – Hannah May Sep 6 '18 at 2:58
0

Currently there is no native function to dissolve scientific notation. However, for this purpose you must write your own functionality.

Here is my:

function dissolveExponentialNotation(number)
{
    if(!Number.isFinite(number)) { return undefined; }

    let text = number.toString();
    let items = text.split('e');

    if(items.length == 1) { return text; }

    let significandText = items[0];
    let exponent = parseInt(items[1]);

    let characters = Array.from(significandText);
    let minus = characters[0] == '-';
    if(minus) { characters.splice(0, 1); }
    let indexDot = characters.reduce((accumulator, character, index) =>
    {
        if(!accumulator.found) { if(character == '.') { accumulator.found = true; } else { accumulator.index++; } }
        return accumulator;
    }, { index: 0, found: false }).index;

    characters.splice(indexDot, 1);

    indexDot += exponent;

    if(indexDot >= 0 && indexDot < characters.length - 1)
    {
        characters.splice(indexDot, 0, '.');
    }
    else if(indexDot < 0)
    {
        characters.unshift("0.", "0".repeat(-indexDot));
    }
    else
    {
        characters.push("0".repeat(indexDot - characters.length));
    }

    return (minus ? "-" : "") + characters.join("");
}
0

You can use from-exponential module. It is lightweight and fully tested.

import fromExponential from 'from-exponential';

fromExponential(1.123e-10); // => '0.0000000001123'
0

You can also use YourJS.fullNumber. For instance YourJS.fullNumber(Number.MAX_VALUE) results in the following: 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

It also works for really small numbers. YourJS.fullNumber(Number.MIN_VALUE) returns this: 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005

It is important to note that this function will always return finite numbers as strings but will return non-finite numbers (eg. NaN or Infinity) as undefined.

You can test it out in the YourJS Console here.

0
function printInt(n) { return n.toPrecision(100).replace(/\..*/,""); }

with some issues:

  • 0.9 is displayed as "0"
  • -0.9 is displayed as "-0"
  • 1e100 is displayed as "1"
  • works only for numbers up to ~1e99 => use other constant for greater numbers; or smaller for optimization.
-1

You can use number.toString(10.1):

console.log(Number.MAX_VALUE.toString(10.1));

Note: This currently works in Chrome, but not in Firefox. The specification says the radix has to be an integer, so this results in unreliable behavior.

-4

I had the same issue with oracle returning scientic notation, but I needed the actual number for a url. I just used a PHP trick by subtracting zero, and I get the correct number.

for example 5.4987E7 is the val.

newval = val - 0;

newval now equals 54987000

  • 2
    This has no effect. 5.4987E7 has an exponent less than 21, so it shows up as the full number regardless when converted to string. (5.4987E21 - 0).toString() => "5.4987e+21" – Dwight Oct 10 '13 at 23:19

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.