web-dev-qa-db-fra.com

Supprimer les zéros de fin non significatifs d'un nombre?

Ai-je raté un appel d'API standard qui supprime les zéros non significatifs d'un nombre?

Ex.

var x = 1.234000 // to become 1.234;
var y = 1.234001; // stays 1.234001

Number.toFixed () et Number.toPrecision () ne sont pas tout à fait ce que je recherche.

111
Steven

Si vous le convertissez en chaîne, les zéros de fin ne sont pas affichés. Ils ne sont pas stockés dans la variable car celle-ci a été créée sous la forme d'un nombre et non d'une chaîne.

var n = 1.245000
var noZeroes = n.toString() // "1.245" 
105
Cristian Sanchez

J'ai eu un cas similaire où je voulais utiliser .toFixed() si nécessaire, mais je ne voulais pas le rembourrage quand ce n'était pas le cas. J'ai donc fini par utiliser parseFloat en conjonction avec toFixed.

toFixed sans padding

parseFloat(n.toFixed(4));

Une autre option qui fait presque la même chose
Cette réponse peut aider votre décision

Number(n.toFixed(4));

toFixed arrondira/complétera le nombre à une longueur spécifique, mais le convertira également en chaîne. La conversion de ce type en un type numérique rendra non seulement le nombre plus sûr pour une utilisation arithmétique, mais supprimera également automatiquement les 0 derniers. Par exemple:

var n = "1.234000";
    n = parseFloat(n);
 // n is 1.234 and in number form

Parce que même si vous définissez un nombre avec des zéros de fin, ils sont supprimés.

var n = 1.23000;
 // n == 1.23;
169
Gary

J'ai d'abord utilisé une combinaison de réponses de matti-lyra et de gary:

r=(+n).toFixed(4).replace(/\.0+$/,'')

Résultats:

  • 1234870.98762341: "1234870.9876"
  • 1230009100: "1230009100"
  • 0.0012234: "0.0012"
  • 0.1200234: "0.12"
  • 0.000001231: "0"
  • 0.10001: "0.1000"
  • "asdf": "NaN" (donc pas d'erreur d'exécution)

Le cas un peu problématique est 0.10001. J'ai fini par utiliser cette version plus longue:

    r = (+n).toFixed(4);
    if (r.match(/\./)) {
      r = r.replace(/\.?0+$/, '');
    }
  • 1234870.98762341: "1234870.9876"
  • 1230009100: "1230009100"
  • 0.0012234: "0.0012"
  • 0.1200234: "0.12"
  • 0.000001231: "0"
  • 0.10001: "0.1"
  • "asdf": "NaN" (donc pas d'erreur d'exécution)

Mise à jour : Et voici la nouvelle version de Gary (voir les commentaires):

r=(+n).toFixed(4).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1')

Cela donne les mêmes résultats que ci-dessus.

21
w00t

La méthode toFixed fera l’arrondi approprié si nécessaire. Cela ajoutera également des zéros à la fin, ce qui n’est pas toujours idéal.

(4.55555).toFixed(2);
//-> "4.56"

(4).toFixed(2);
//-> "4.00"

Si vous convertissez la valeur de retour en nombre, les zéros à la fin seront supprimés. C'est une approche plus simple que de faire votre propre calcul d'arrondi ou de troncature.

+(4.55555).toFixed(2);
//-> 4.56

+(4).toFixed(2);
//-> 4
9
C. J.

J'avais également besoin de résoudre ce problème lorsque Django affichait des valeurs de type Decimal dans un champ de texte. Par exemple. quand '1' était la valeur. Il montrerait '1.00000000'. Si "1,23" était la valeur, "1,23000000" serait indiqué (dans le cas d'un paramètre "decimal_places" de 8)

Utiliser parseFloat n'était pas une option pour moi car il est possible que la même valeur ne soit pas renvoyée. toFixed n'était pas une option car je ne voulais rien arrondir, alors j'ai créé une fonction:

function removeTrailingZeros(value) {
    value = value.toString();

    # if not containing a dot, we do not need to do anything
    if (value.indexOf('.') === -1) {
        return value;
    }

    # as long as the last character is a 0 or a dot, remove it
    while((value.slice(-1) === '0' || value.slice(-1) === '.') && value.indexOf('.') !== -1) {
        value = value.substr(0, value.length - 1);
    }
    return value;
}
6
megasnort

J'avais fondamentalement la même exigence et j'ai constaté qu'il n'y avait pas de mécanisme intégré pour cette fonctionnalité. 

En plus de réduire les zéros de fin, j’ai également besoin d’arrondir et éventuellement de formater la sortie pour les paramètres régionaux actuels de l’utilisateur (c’est-à-dire 123,456.789).

Tout mon travail sur cela a été inclus en tant que prettyFloat.js (sous licence MIT) sur GitHub: https://github.com/dperish/prettyFloat.js


Exemples d'utilisation:

prettyFloat(1.111001, 3) // "1.111"
prettyFloat(1.111001, 4) // "1.111"
prettyFloat(1.1111001, 5) // "1.1111"
prettyFloat(1234.5678, 2) // "1234.57"
prettyFloat(1234.5678, 2, true) // "1,234.57" (en-us)


Mise à jour - août 2018


Tous les navigateurs modernes prennent désormais en charge la API d'internationalisation ECMAScript , qui fournit une comparaison de chaînes sensible à la langue, le formatage des nombres et le formatage de la date et de l'heure. 

let formatters = {
    default: new Intl.NumberFormat(),
    currency: new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 0, maximumFractionDigits: 0 }),
    whole: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 0, maximumFractionDigits: 0 }),
    oneDecimal: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 1, maximumFractionDigits: 1 }),
    twoDecimal: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2 })
};

formatters.twoDecimal.format(1234.5678);  // result: "1,234.57"
formatters.currency.format(28761232.291); // result: "$28,761,232"

Pour les anciens navigateurs, vous pouvez utiliser ce polyfill: https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en

4
dperish

Pourquoi ne pas simplement multiplier par un comme ceci?

var x = 1.234000*1; // becomes 1.234

var y = 1.234001*1; // stays as 1.234001
2
Howard

Aucune de ces solutions ne fonctionnait pour moi pour un très petit nombre. http://numeraljs.com/ a résolu ce problème pour moi.

parseFloat(0.00000001.toFixed(8));
// 1e-8

numeral(0.00000001).format('0[.][00000000]');
// "0.00000001"
2
Devon

Réponse regex pure

n.replace(/(\.[0-9]*[1-9])0+$|\.0*$/,'$1');

Je me demande pourquoi personne n'en a donné un!

1
João Costa

Vous pouvez essayer celui-ci pour minimiser les nombres flottants

var n = 0.0000;
n = parseFloat(n.toString()); 

//output n = 0; 
// n = 3.14000; --> n = 3.14;
1
Amit Panasara

Si vous ne pouvez pas utiliser Floats pour quelque raison que ce soit (par exemple money-floats) et si vous commencez déjà par une chaîne représentant un nombre correct, vous pouvez trouver cette solution pratique. Il convertit une chaîne représentant un nombre en une chaîne représentant un nombre sans zéros à la fin.

function removeTrailingZeroes( strAmount ) {
    // remove all trailing zeroes in the decimal part
    var strDecSepCd = '.'; // decimal separator
    var iDSPosition = strAmount.indexOf( strDecSepCd ); // decimal separator positions
    if ( iDSPosition !== -1 ) {
        var strDecPart = strAmount.substr( iDSPosition ); // including the decimal separator

        var i = strDecPart.length - 1;
        for ( ; i >= 0 ; i-- ) {
            if ( strDecPart.charAt(i) !== '0') {
                break;
            }
        }

        if ( i=== 0 ) {
            return strAmount.substring(0, iDSPosition);
        } else {
            // return INTPART and DS + DECPART including the rightmost significant number
            return strAmount.substring(0, iDSPosition) + strDecPart.substring(0,i + 1);
        }
    }

    return strAmount;
}
0
BennyHilarious

J'avais besoin de supprimer tous les zéros de fin mais de garder au moins 2 décimales, y compris tous les zéros.
Les nombres sur lesquels je travaille sont des chaînes à 6 nombres décimaux, générées par .toFixed (6).

Résultat attendu:

var numstra = 12345.000010 // should return 12345.00001
var numstrb = 12345.100000 // should return 12345.10
var numstrc = 12345.000000 // should return 12345.00
var numstrd = 12345.123000 // should return 12345.123

Solution:

var numstr = 12345.100000

while (numstr[numstr.length-1] === "0") {           
    numstr = numstr.slice(0, -1)
    if (numstr[numstr.length-1] !== "0") {break;}
    if (numstr[numstr.length-3] === ".") {break;}
}

console.log(numstr) // 12345.10

Logique:

Exécuter une fonction en boucle si le dernier caractère de la chaîne est un zéro.
Supprimez le dernier caractère et mettez à jour la variable chaîne.
Si la chaîne mise à jour, le dernier caractère n'est pas une boucle zéro.
Si la chaîne mise à jour du troisième au dernier caractère est une virgule flottante, boucle de fin.

0
Kevin H.

Après avoir lu toutes les réponses - et commentaires - je me suis retrouvé avec ceci:

function isFloat(n) {
    let number = (Number(n) === n && n % 1 !== 0) ? eval(parseFloat(n)) : n;
    return number;
}

Je sais que l'utilisation de eval peut être nuisible, mais cela m'a beaucoup aidé.

Alors:

isFloat(1.234000);     // = 1.234;
isFloat(1.234001);     // = 1.234001
isFloat(1.2340010000); // = 1.234001

Si vous souhaitez limiter les décimales, utilisez toFixed() comme d'autres l'ont souligné.

let number = (Number(n) === n && n % 1 !== 0) ? eval(parseFloat(n).toFixed(3)) : n;

C'est tout.

0
ed1nh0

Voici une solution possible:

var x = 1.234000 // to become 1.234;
var y = 1.234001; // stays 1.234001

eval(x) --> 1.234
eval(y) --> 1.234001
0
Moon