web-dev-qa-db-fra.com

Comment éviter la notation scientifique pour les grands nombres en JavaScript?

JavaScript convertit une grande INT en notation scientifique lorsque le nombre devient grand. Comment puis-je empêcher cela?

138
chris

Il existe Number.toFixed , mais il utilise la notation scientifique si le nombre est> = 1e21 et a une précision maximale de 20. Sinon, vous pouvez obtenir le vôtre, mais ce sera désordonné.

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

La méthode ci-dessus utilise la répétition de chaîne bon marché, facile. ((new Array(n+1)).join(str)). Vous pouvez définir String.prototype.repeat en utilisant la multiplication des paysans russes et l'utiliser à la place.

Cette réponse ne devrait être appliquée qu'au contexte de la question: afficher un grand nombre sans utiliser de notation scientifique. Pour toute autre chose, vous devriez utiliser une bibliothèque BigInt , telle que BigNumber , BigInt de Leemon ou BigInteger . À l'avenir, un projet de BigInt (note: pas celle de Leemon) devrait être pris en charge de manière native ( Chrome est pris en charge et il est en cours de traitement pour Firefox ).

96
outis

Pour un petit nombre et savoir combien de décimales vous voulez, vous pouvez utiliser toFixed puis utiliser une expression rationnelle pour supprimer les zéros de fin.

Number(1e-7).toFixed(8).replace(/\.?0+$/,"") //0.000
18
Niklas Forsström

une autre solution possible:

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

Je sais que c'est une question plus ancienne, mais montre récemment actif. 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"

vous pouvez utiliser les options pour formater la sortie.

Remarque:

Number.toLocaleString () arrondit après 16 décimales, pour que ...

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

...résultats...

586084736227728400000000000000000000000

Cela n’est peut-être pas souhaitable si la précision est importante dans le résultat souhaité.

11
flapjack17

Voici ma courte variante de Number.prototype.toFixed qui fonctionne avec n'importe quel nombre:

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"
8
VisioN

La solution suivante contourne la mise en forme exponentielle automatique pour les très grands et les très petits nombres. C'est la solution de outis avec un correctif: cela ne fonctionnait pas pour les très petits nombres négatifs.

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

6
Jenny O'Reilly

Y__extrait de code__

// 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;
  }
}
3
Tyeth

Je pense qu'il peut y avoir plusieurs réponses similaires, mais voici une chose que je suis venu avec

// 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);

Remarque: cette opération est aussi précise que les fonctions mathématiques javascript et pose des problèmes lors de l’utilisation de log au lieu de log10 sur la ligne précédant la boucle for; il écrira 1000 en base 10 en tant que 000; je l’ai donc changé en log10, car les utilisateurs utiliseront surtout la base 10 de toute façon.

Ce n'est peut-être pas une solution très précise, mais je suis fier de pouvoir dire qu'il peut traduire les chiffres d'une base à l'autre avec une option pour les virgules!

2
cmarangu

J'ai essayé de travailler avec la forme de chaîne plutôt que le nombre et cela semblait fonctionner. Je n'ai testé cela que sur Chrome, mais cela devrait être universel:

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
Sanford Staab

Vous pouvez faire une boucle sur le nombre et arrondir

// fonctionnalité pour remplacer char à l'index donné

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

// boucle sur le nombre commence

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
Kapil gopinath

Ta question:

number :0x68656c6c6f206f72656f display:4.9299704811152646e+23

vous pouvez utiliser ceci: https://github.com/MikeMcl/bignumber.js

Une bibliothèque JavaScript pour l'arithmétique décimale et non décimale à précision arbitraire.

comme ça :

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

1
super2bai

Utilisez cette fonction:

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

Je sais que cela se passe de nombreuses années plus tard, mais je travaillais sur un problème similaire récemment et je voulais publier ma solution. La réponse actuellement acceptée compense la partie de l'exposant avec des 0, et la mienne tente de trouver la réponse exacte, bien qu'elle ne soit généralement pas parfaitement exacte pour les très grands nombres en raison de la précision de JS en virgule flottante.

Cela fonctionne pour Math.pow(2, 100), en renvoyant la valeur correcte de 1267650600228229401496963205376.

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
andi

Utilisez .toPrecision, .toFixed, etc. Vous pouvez compter le nombre de chiffres de votre numéro en le convertissant en chaîne avec .toString, puis en regardant son .length.

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

avec quelques problèmes:

  • 0.9 est affiché comme "0"
  • -0.9 est affiché comme "-0"
  • 1e100 est affiché comme "1"
  • ne fonctionne que pour les nombres jusqu’à ~ 1e99 => utilisez une autre constante pour les plus grands nombres; ou plus petit pour l'optimisation.
0
Wiimm

Vous pouvez également utiliser YourJS.fullNumber. Par exemple, YourJS.fullNumber(Number.MAX_VALUE) donne les résultats suivants: 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Cela fonctionne aussi pour de très petits nombres. YourJS.fullNumber(Number.MIN_VALUE) renvoie ceci: 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005

Il est important de noter que cette fonction retournera toujours des nombres finis sous forme de chaînes mais renverra des nombres non finis (par exemple, NaN ou Infinity) sous la forme undefined.

Vous pouvez le tester dans la console YourJS Console ici .

0
Chris West

Vous pouvez utiliser from-exponential module. Il est léger et entièrement testé.

import fromExponential from 'from-exponential';

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

Si vous ne le faites que pour l'affichage, vous pouvez construire un tableau à partir des chiffres avant qu'ils ne soient arrondis.

var num = Math.pow(2, 100);
var reconstruct = [];
while(num > 0) {
    reconstruct.unshift(num % 10);
    num = Math.floor(num / 10);
}
console.log(reconstruct.join(''));
0
Jake M

Actuellement, il n'y a pas de fonction native pour dissoudre la notation scientifique. Cependant, pour cela, vous devez écrire votre propre fonctionnalité.

Voici mon:

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
Martin Wantke