[javascript] How to avoid scientific notation for large numbers in JavaScript?

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

This question is related to javascript

The answer is


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.


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;
}

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(''));

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;
}

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("");
}

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;
  }
}

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.

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


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.


The answers of others do not give you the exact number!
This function calculates the desired number accurately and returns it in the string to prevent it from being changed by javascript!
If you need a numerical result, just multiply the result of the function in number one!

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 calculate the absolute 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;
}

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.


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

Busting out the regular expressions. This has no precision issues and is not a lot of code.

_x000D_
_x000D_
function toPlainString(num) {
  return (''+ +num).replace(/(-?)(\d*)\.?(\d*)e([+-]\d+)/,
    function(a,b,c,d,e) {
      return e < 0
        ? b + '0.' + Array(1-e-c.length).join(0) + c + d
        : b + c + d + Array(e-d.length+1).join(0);
    });
}

console.log(toPlainString(12345e+12));
console.log(toPlainString(12345e+24));
console.log(toPlainString(-12345e+24));
console.log(toPlainString(12345e-12));
console.log(toPlainString(123e-12));
console.log(toPlainString(-123e-12));
console.log(toPlainString(-123.45e-56));
console.log(toPlainString('1e-8'));
console.log(toPlainString('1.0e-8'));
_x000D_
_x000D_
_x000D_


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.


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

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!


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.

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

import fromExponential from 'from-exponential';

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

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

_x000D_
_x000D_
Number.prototype.toFixedSpecial = function(n) {_x000D_
  var str = this.toFixed(n);_x000D_
  if (str.indexOf('e+') === -1)_x000D_
    return str;_x000D_
_x000D_
  // if number is in scientific notation, pick (b)ase and (p)ower_x000D_
  str = str.replace('.', '').split('e+').reduce(function(p, b) {_x000D_
    return p + Array(b - p.length + 2).join(0);_x000D_
  });_x000D_
  _x000D_
  if (n > 0)_x000D_
    str += '.' + Array(n + 1).join(0);_x000D_
  _x000D_
  return str;_x000D_
};_x000D_
_x000D_
console.log( 1e21.toFixedSpecial(2) );       // "1000000000000000000000.00"_x000D_
console.log( 2.1e24.toFixedSpecial(0) );     // "2100000000000000000000000"_x000D_
console.log( 1234567..toFixedSpecial(1) );   // "1234567.0"_x000D_
console.log( 1234567.89.toFixedSpecial(3) ); // "1234567.890"
_x000D_
_x000D_
_x000D_


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.

_x000D_
_x000D_
function numberToString(num)_x000D_
{_x000D_
    let numStr = String(num);_x000D_
_x000D_
    if (Math.abs(num) < 1.0)_x000D_
    {_x000D_
        let e = parseInt(num.toString().split('e-')[1]);_x000D_
        if (e)_x000D_
        {_x000D_
            let negative = num < 0;_x000D_
            if (negative) num *= -1_x000D_
            num *= Math.pow(10, e - 1);_x000D_
            numStr = '0.' + (new Array(e)).join('0') + num.toString().substring(2);_x000D_
            if (negative) numStr = "-" + numStr;_x000D_
        }_x000D_
    }_x000D_
    else_x000D_
    {_x000D_
        let e = parseInt(num.toString().split('+')[1]);_x000D_
        if (e > 20)_x000D_
        {_x000D_
            e -= 20;_x000D_
            num /= Math.pow(10, e);_x000D_
            numStr = num.toString() + (new Array(e + 1)).join('0');_x000D_
        }_x000D_
    }_x000D_
_x000D_
    return numStr;_x000D_
}_x000D_
_x000D_
// testing ..._x000D_
console.log(numberToString(+0.0000000000000000001));_x000D_
console.log(numberToString(-0.0000000000000000001));_x000D_
console.log(numberToString(+314564649798762418795));_x000D_
console.log(numberToString(-314564649798762418795));
_x000D_
_x000D_
_x000D_


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--;
 }
}

The question of the post was avoiding e notation numbers and having the number as a plain number.

Therefore, if all is needed is to convert e (scientific) notation numbers to plain numbers (including in the case of fractional numbers) without loss of accuracy, then it is essential to avoid the use of the Math object and other javascript number methods so that rounding does not occur when large numbers and large fractions are handled (which always happens due to the internal storage in binary format).

The following function converts e (scientific) notation numbers to plain numbers (including fractions) handling both large numbers and large fractions without loss of accuracy as it does not use the built-in math and number functions to handle or manipulate the number.

The function also handles normal numbers, so that a number that is suspected to become in an 'e' notation can be passed to the function for fixing.

The function should work with different locale decimal points.

94 test cases are provided.

For large e-notation numbers pass the number as a string.

Examples:

eToNumber("123456789123456789.111122223333444455556666777788889999e+50");
// output:
"12345678912345678911112222333344445555666677778888999900000000000000"
eToNumber("123.456123456789123456895e-80");
// output:
"0.00000000000000000000000000000000000000000000000000000000000000000000000000000123456123456789123456895"
eToNumber("123456789123456789.111122223333444455556666777788889999e-50");
// output:
"0.00000000000000000000000000000000123456789123456789111122223333444455556666777788889999"

Valid e-notation numbers in Javascript include the following:

123e1   ==> 1230
123E1   ==> 1230
123e+1  ==> 1230
123.e+1 ==> 1230
123e-1  ==> 12.3
0.1e-1  ==> 0.01
.1e-1   ==> 0.01
-123e1  ==> -1230

_x000D_
_x000D_
/******************************************************************
 * Converts e-Notation Numbers to Plain Numbers
 ******************************************************************
 * @function eToNumber(number)
 * @version  1.00
 * @param   {e nottation Number} valid Number in exponent format.
 *          pass number as a string for very large 'e' numbers or with large fractions
 *          (none 'e' number returned as is).
 * @return  {string}  a decimal number string.
 * @author  Mohsen Alyafei
 * @date    17 Jan 2020
 * Note: No check is made for NaN or undefined input numbers.
 *
 *****************************************************************/
function eToNumber(num) {
  let sign = "";
  (num += "").charAt(0) == "-" && (num = num.substring(1), sign = "-");
  let arr = num.split(/[e]/ig);
  if (arr.length < 2) return sign + num;
  let dot = (.1).toLocaleString().substr(1, 1), n = arr[0], exp = +arr[1];
  let w = (n = n.replace(/^0+/, '')).replace(dot, ''),
    pos = n.split(dot)[1] ? n.indexOf(dot) + exp : w.length + exp,
    L = pos - w.length, s = "" + BigInt(w);
  w = exp >= 0 ? (L >= 0 ? s + "0".repeat(L) : r()) : (pos <= 0 ? "0" + dot + "0".repeat(Math.abs(pos)) + s : r());
  if (!+w) w = 0; return sign + w;
  function r() {return w.replace(new RegExp(`^(.{${pos}})(.)`), `$1${dot}$2`)}
}
//*****************************************************************

//================================================
//             Test Cases
//================================================
let r = 0; // test tracker
r |= test(1, "123456789123456789.111122223333444455556666777788889999e+50", "12345678912345678911112222333344445555666677778888999900000000000000");
r |= test(2, "123456789123456789.111122223333444455556666777788889999e-50", "0.00000000000000000000000000000000123456789123456789111122223333444455556666777788889999");
r |= test(3, "123456789e3", "123456789000");
r |= test(4, "123456789e1", "1234567890");
r |= test(5, "1.123e3", "1123");
r |= test(6, "12.123e3", "12123");
r |= test(7, "1.1234e1", "11.234");
r |= test(8, "1.1234e4", "11234");
r |= test(9, "1.1234e5", "112340");
r |= test(10, "123e+0", "123");
r |= test(11, "123E0", "123");
// //============================
r |= test(12, "123e-1", "12.3");
r |= test(13, "123e-2", "1.23");
r |= test(14, "123e-3", "0.123");
r |= test(15, "123e-4", "0.0123");
r |= test(16, "123e-2", "1.23");
r |= test(17, "12345.678e-1", "1234.5678");
r |= test(18, "12345.678e-5", "0.12345678");
r |= test(19, "12345.678e-6", "0.012345678");
r |= test(20, "123.4e-2", "1.234");
r |= test(21, "123.4e-3", "0.1234");
r |= test(22, "123.4e-4", "0.01234");
r |= test(23, "-123e+0", "-123");
r |= test(24, "123e1", "1230");
r |= test(25, "123e3", "123000");
r |= test(26, -1e33, "-1000000000000000000000000000000000");
r |= test(27, "123e+3", "123000");
r |= test(28, "123E+7", "1230000000");
r |= test(29, "-123.456e+1", "-1234.56");
r |= test(30, "-1.0e+1", "-10");
r |= test(31, "-1.e+1", "-10");
r |= test(32, "-1e+1", "-10");
r |= test(34, "-0", "-0");
r |= test(37, "0e0", "0");
r |= test(38, "123.456e+4", "1234560");
r |= test(39, "123E-0", "123");
r |= test(40, "123.456e+50", "12345600000000000000000000000000000000000000000000000");

r |= test(41, "123e-0", "123");
r |= test(42, "123e-1", "12.3");
r |= test(43, "123e-3", "0.123");
r |= test(44, "123.456E-1", "12.3456");
r |= test(45, "123.456123456789123456895e-80", "0.00000000000000000000000000000000000000000000000000000000000000000000000000000123456123456789123456895");
r |= test(46, "-123.456e-50", "-0.00000000000000000000000000000000000000000000000123456");

r |= test(47, "-0e+1", "-0");
r |= test(48, "0e+1", "0");
r |= test(49, "0.1e+1", "1");
r |= test(50, "-0.01e+1", "-0.1");
r |= test(51, "0.01e+1", "0.1");
r |= test(52, "-123e-7", "-0.0000123");
r |= test(53, "123.456e-4", "0.0123456");

r |= test(54, "1.e-5", "0.00001"); // handle missing base fractional part
r |= test(55, ".123e3", "123"); // handle missing base whole part

// The Electron's Mass:
r |= test(56, "9.10938356e-31", "0.000000000000000000000000000000910938356");
// The Earth's Mass:
r |= test(57, "5.9724e+24", "5972400000000000000000000");
// Planck constant:
r |= test(58, "6.62607015e-34", "0.000000000000000000000000000000000662607015");

r |= test(59, "0.000e3", "0");
r |= test(60, "0.000000000000000e3", "0");
r |= test(61, "-0.0001e+9", "-100000");
r |= test(62, "-0.0e1", "-0");
r |= test(63, "-0.0000e1", "-0");


r |= test(64, "1.2000e0", "1.2000");
r |= test(65, "1.2000e-0", "1.2000");
r |= test(66, "1.2000e+0", "1.2000");
r |= test(67, "1.2000e+10", "12000000000");
r |= test(68, "1.12356789445566771234e2", "112.356789445566771234");

// ------------- testing for Non e-Notation Numbers -------------
r |= test(69, "12345.7898", "12345.7898") // no exponent
r |= test(70, 12345.7898, "12345.7898") // no exponent
r |= test(71, 0.00000000000001, "0.00000000000001") // from 1e-14
r |= test(72, 0.0000000000001, "0.0000000000001") // from 1e-13
r |= test(73, 0.000000000001, "0.000000000001") // from 1e-12
r |= test(74, 0.00000000001, "0.00000000001") // from 1e-11
r |= test(75, 0.0000000001, "0.0000000001") // from 1e-10
r |= test(76, 0.000000001, "0.000000001") // from 1e-9
r |= test(77, 0.00000001, "0.00000001") // from 1e-8
r |= test(78, 0.0000001, "0.0000001") // from 1e-7
r |= test(79, 1e-7, "0.0000001") // from 1e-7
r |= test(80, -0.0000001, "-0.0000001") // from 1e-7
r |= test(81, 0.0000005, "0.0000005") // from 1e-7
r |= test(82, 0.1000005, "0.1000005") // from 1e-7
r |= test(83, 1e-6, "0.000001") // from 1e-6

r |= test(84, 0.000001, "0.000001"); // from 1e-6
r |= test(85, 0.00001, "0.00001"); // from 1e-5
r |= test(86, 0.0001, "0.0001"); // from 1e-4
r |= test(87, 0.001, "0.001"); // from 1e-3
r |= test(88, 0.01, "0.01"); // from 1e-2
r |= test(89, 0.1, "0.1") // from 1e-1
r |= test(90, -0.0000000000000345, "-0.0000000000000345"); // from -3.45e-14
r |= test(91, -0, "0");
r |= test(92, "-0", "-0");
r |= test(93,2e64,"20000000000000000000000000000000000000000000000000000000000000000");
r |= test(94,"2830869077153280552556547081187254342445169156730","2830869077153280552556547081187254342445169156730");

if (r == 0) console.log("All 94 tests passed.");

//================================================
//             Test function
//================================================
function test(testNumber, n1, should) {
  let result = eToNumber(n1);
  if (result !== should) {
    console.log(`Test ${testNumber} Failed. Output: ${result}\n             Should be: ${should}`);
    return 1;
  }
}
_x000D_
_x000D_
_x000D_


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