Formatage d'un nombre avec exactement deux décimales en JavaScript

571

J'ai cette ligne de code qui arrondit mes nombres à deux décimales. Mais je reçois des nombres comme celui-ci: 10,8, 2,4, etc. Ce n'est pas mon idée de deux décimales, alors comment améliorer les éléments suivants?

Math.round(price*Math.pow(10,2))/Math.pow(10,2);

Je veux des nombres comme 10.80, 2.40, etc. L'utilisation de jQuery me convient.

Abdos
la source
1
Votre code est exactement ce que je cherchais (pour réduire la précision du flottant à 7 décimales pour un fichier JSON plus petit). Ignorer Math.pow pour la vitesse val = Math.round (val * 10000000) / 10000000);
Pawel
Comme la réponse actuellement acceptée donne sans doute un mauvais résultat pour un large éventail de valeurs grâce à l' imprécision inhérente à l' aggravation des chiffres ( 0.565, 0.575, 1.005), puis - je suggérer à la recherche de nouveau à cette réponse , ce qui les obtient corriger?
TJ Crowder du
Peut-être que vous souhaitez inclure une bibliothèque sprintf pour JavaScript stackoverflow.com/questions/610406/…
Thilo
Après avoir arrondi correctement avec la méthode de décalage et d'arrondi à la décimale, vous pouvez utiliser la number.toFixed(x)méthode pour la convertir en une chaîne avec le nombre de zéros requis. Par exemple, arrondissez 1.34à 1.3avec la méthode multi-navigateur, puis ajoutez 1 zéro et convertissez-le en chaîne avec 1.3.toFixed(2)(pour obtenir "1.30").
Edward

Réponses:

999

Pour formater un nombre à l'aide de la notation à virgule fixe, vous pouvez simplement utiliser la méthode toFixed :

(10.8).toFixed(2); // "10.80"

var num = 2.4;
alert(num.toFixed(2)); // "2.40"

Notez que toFixed()renvoie une chaîne.

IMPORTANT : notez que toFixed n'arrondit pas 90% du temps, il renverra la valeur arrondie, mais dans de nombreux cas, cela ne fonctionne pas.

Par exemple:

2.005.toFixed(2) === "2.00"

MISE À JOUR:

De nos jours, vous pouvez utiliser le Intl.NumberFormatconstructeur. Cela fait partie de la spécification ECMAScript Internationalization API (ECMA402). Il a très bon soutien du navigateur , y compris même IE11, et il est entièrement pris en charge Node.js .

const formatter = new Intl.NumberFormat('en-US', {
   minimumFractionDigits: 2,      
   maximumFractionDigits: 2,
});

console.log(formatter.format(2.005)); // "2.01"
console.log(formatter.format(1.345)); // "1.35"

Vous pouvez également utiliser la toLocaleStringméthode, qui en interne utilisera l' IntlAPI:

const format = (num, decimals) => num.toLocaleString('en-US', {
   minimumFractionDigits: 2,      
   maximumFractionDigits: 2,
});


console.log(format(2.005)); // "2.01"
console.log(format(1.345)); // "1.35"

Cette API vous offre également une grande variété d'options de formatage, comme des milliers de séparateurs, des symboles monétaires, etc.

CMS
la source
17
Ne fonctionne pas de manière cohérente sur tous les navigateurs, c'est-à-dire (0.09).toFixed(1);donne 0,0 dans IE8
ajbeaven
41
fixed ne s'arrondit pas, vous pouvez le faire en premier: (Math.round (0.09)). toFixed (1);
rekans
32
@rekans: C'est faux. Math.Round(0.09)reviendra 0donc cela donnera toujours 0.0...
Chris
28
C'est une mauvaise idée dans la plupart des situations, cela convertit le nombre en une chaîne ou un nombre à virgule flottante dans certains cas.
Ash Blue
80
Je dois être d'accord avec @AshBlue ici ... ce n'est sûr que pour le formatage de la présentation des valeurs. Peut casser le code avec d'autres calculs. Sinon, Math.round(value*100)/100fonctionne mieux pour 2DP.
UpTheCreek
98

Il s'agit d'un sujet ancien, mais toujours parmi les meilleurs résultats de Google et les solutions proposées partagent le même problème de décimales à virgule flottante. Voici la fonction (très générique) que j'utilise, grâce à MDN :

function round(value, exp) {
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp = +exp;

  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}

Comme nous pouvons le voir, nous n'obtenons pas ces problèmes:

round(1.275, 2);   // Returns 1.28
round(1.27499, 2); // Returns 1.27

Cette généricité fournit également des trucs sympas:

round(1234.5678, -2);   // Returns 1200
round(1.2345678e+2, 2); // Returns 123.46
round("123.45");        // Returns 123

Maintenant, pour répondre à la question du PO, il faut taper:

round(10.8034, 2).toFixed(2); // Returns "10.80"
round(10.8, 2).toFixed(2);    // Returns "10.80"

Ou, pour une fonction plus concise et moins générique:

function round2Fixed(value) {
  value = +value;

  if (isNaN(value))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + 2) : 2)));

  // Shift back
  value = value.toString().split('e');
  return (+(value[0] + 'e' + (value[1] ? (+value[1] - 2) : -2))).toFixed(2);
}

Vous pouvez l'appeler avec:

round2Fixed(10.8034); // Returns "10.80"
round2Fixed(10.8);    // Returns "10.80"

Divers exemples et tests (merci à @ tj-crowder !):

astorije
la source
1
Comment n'y a-t-il pas un moyen simple de procéder? ES6 à la rescousse?
zero_cool
Merci d'avoir publié le polyfill MDN. Sur la page MDN liée, le polyfill n'est plus là. Je me demande pourquoi il a été retiré ...
King Holly
43

J'ajoute généralement cela à ma bibliothèque personnelle, et après quelques suggestions et en utilisant également la solution @TIMINeutron, et en la rendant adaptable à la longueur décimale, celle-ci convient le mieux:

function precise_round(num, decimals) {
   var t = Math.pow(10, decimals);   
   return (Math.round((num * t) + (decimals>0?1:0)*(Math.sign(num) * (10 / Math.pow(100, decimals)))) / t).toFixed(decimals);
}

fonctionnera pour les exceptions signalées.

Miguel
la source
2
precise_round (1.275,2) est 1,27?
allenhwkim
2
@Imre Remplacez la valeur de retour par (Math.round (num * Math.pow (10, décimales)) / Math.pow (10, décimales)). ToFixed (2); et vous n'aurez plus ce problème.
dkroy
6
où déclarez-vous "signe" et "déc" si votre deuxième fonction est récupérée telle quelle ne devrait-elle pas les avoir comme non définies?
Ady Ngom
2
J'ai ajouté une solution de contournement pour la méthode de signe d'erreur dans IE: gist.github.com/ArminVieweg/28647e735aa6efaba401
Armin
1
@Armin Votre correctif le fait également fonctionner dans Safari. La fonction d'origine ne fonctionnait pas dans Safari.
Dave
19

Je ne sais pas pourquoi je ne peux pas ajouter de commentaire à une réponse précédente (peut-être que je suis désespérément aveugle, ne sais pas), mais j'ai trouvé une solution en utilisant la réponse de @ Miguel:

function precise_round(num,decimals) {
   return Math.round(num*Math.pow(10, decimals)) / Math.pow(10, decimals);
}

Et ses deux commentaires (de @bighostkim et @Imre):

  • Problème de precise_round(1.275,2)non retour 1.28
  • Problème de precise_round(6,2)ne pas retourner 6h00 (comme il le voulait).

Ma solution finale est la suivante:

function precise_round(num,decimals) {
    var sign = num >= 0 ? 1 : -1;
    return (Math.round((num*Math.pow(10,decimals)) + (sign*0.001)) / Math.pow(10,decimals)).toFixed(decimals);
}

Comme vous pouvez le voir, j'ai dû ajouter un peu de "correction" (ce n'est pas ce que c'est, mais puisque Math.round est avec perte - vous pouvez le vérifier sur jsfiddle.net - c'est la seule façon dont j'ai su "corriger" " il). Il ajoute 0,001 au nombre déjà complété, il ajoute donc 1trois 0s à droite de la valeur décimale. Il devrait donc être sûr à utiliser.

Après cela, j'ai ajouté .toFixed(decimal)pour toujours afficher le nombre au format correct (avec la bonne quantité de décimales).

C'est à peu près tout. Utilisez-le bien;)

EDIT: ajout de fonctionnalités à la "correction" des nombres négatifs.

tfrascaroli
la source
2
La « correction » est la plupart du temps en toute sécurité, mais par exemple , precise_round(1.27499,2)retourne maintenant 1,28 ... Ce n'est pas Math.roundqui est lossy; la façon dont les ordinateurs stockent en interne les valeurs à virgule flottante. Fondamentalement, vous êtes voué à l'échec avec certaines valeurs avant même que les données n'atteignent votre fonction :)
Imre
@Imre, vous avez absolument raison. C'est pourquoi j'explique ce que fait ce 0.001 là, au cas où quelqu'un voudrait le rendre "plus précis " ou même le supprimer (si vous avez un super ordinateur avec 2 Mo par flotteur, ce que je ne pense pas que quiconque ici fasse ;)
tfrascaroli
1
En fait, la spécification du langage est assez spécifique sur l'utilisation de 64 bits pour les valeurs numériques, donc avoir / utiliser un supercalculateur ne changerait rien :)
Imre
pour le 0,001, vous pouvez remplacer en ajoutant de nombreux zéros selon la longueur des décimales. alors ..
Miguel
15

Une façon d'être sûr à 100% que vous obtenez un nombre avec 2 décimales:

(Math.round(num*100)/100).toFixed(2)

Si cela provoque des erreurs d'arrondi, vous pouvez utiliser ce qui suit comme James l'a expliqué dans son commentaire:

(Math.round((num * 1000)/10)/100).toFixed(2)
Gerard de Visser
la source
6
C'est la meilleure façon de le faire. Cependant, en raison des calculs en virgule flottante, 1,275 * 100 = 127,49999999999999, ce qui pourrait provoquer des erreurs mineures dans l'arrondi. Pour résoudre ce problème, nous pouvons multiplier par 1000 et diviser par 10, comme (1,275 * 1000) / 10 = 127,5. Comme suit: var answer = (Math.round((num * 1000)/10)/100).toFixed(2);
James Gould
(Math.round ((1.015 * 1000) / 10) / 100) .toFixed (2) donne toujours 1.01, ne devrait-il pas être 1.02?
gaurav5430
14

toFixed (n) fournit n longueur après le point décimal; toPrecision (x) fournit x longueur totale.

Utilisez cette méthode ci-dessous

// Example: toPrecision(4) when the number has 7 digits (3 before, 4 after)
    // It will round to the tenths place
    num = 500.2349;
    result = num.toPrecision(4); // result will equal 500.2

ET si vous voulez que le numéro soit fixe, utilisez

result = num.toFixed(2);
Syed Umar Ahmed
la source
cela ne fonctionne pas bien ... pour le numéro num = 50.2349, vous devez écrire à Precision (3) pour obtenir 50.2
Piotr Czyż
c'est juste un exemple, vous pouvez le changer selon vos besoins @ PiotrCzyż
Syed Umar Ahmed
5

Je n'ai pas trouvé de solution précise à ce problème, j'ai donc créé la mienne:

function inprecise_round(value, decPlaces) {
  return Math.round(value*Math.pow(10,decPlaces))/Math.pow(10,decPlaces);
}

function precise_round(value, decPlaces){
    var val = value * Math.pow(10, decPlaces);
    var fraction = (Math.round((val-parseInt(val))*10)/10);

    //this line is for consistency with .NET Decimal.Round behavior
    // -342.055 => -342.06
    if(fraction == -0.5) fraction = -0.6;

    val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
    return val;
}

Exemples:

function inprecise_round(value, decPlaces) {
  return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}

function precise_round(value, decPlaces) {
  var val = value * Math.pow(10, decPlaces);
  var fraction = (Math.round((val - parseInt(val)) * 10) / 10);

  //this line is for consistency with .NET Decimal.Round behavior
  // -342.055 => -342.06
  if (fraction == -0.5) fraction = -0.6;

  val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
  return val;
}

// This may produce different results depending on the browser environment
console.log("342.055.toFixed(2)         :", 342.055.toFixed(2)); // 342.06 on Chrome & IE10

console.log("inprecise_round(342.055, 2):", inprecise_round(342.055, 2)); // 342.05
console.log("precise_round(342.055, 2)  :", precise_round(342.055, 2));   // 342.06
console.log("precise_round(-342.055, 2) :", precise_round(-342.055, 2));  // -342.06

console.log("inprecise_round(0.565, 2)  :", inprecise_round(0.565, 2));   // 0.56
console.log("precise_round(0.565, 2)    :", precise_round(0.565, 2));     // 0.57

Florian Ignaz Eßl
la source
2
Merci. Voici une chanson pour tester cela: jsfiddle.net/lamarant/ySXuF . J'applique toFixed () à la valeur avant de la renvoyer, ce qui ajoute le nombre correct de zéros à la fin de la valeur renvoyée.
lamarant
ne fonctionne pas pour la valeur = 0,004990845956707237 et inprecise_round (valeur, 8) renvoie 0,00499085 mais il doit renvoyer 0,00499084
MERT DOĞAN
3

@heridev et moi avons créé une petite fonction dans jQuery.

Vous pouvez essayer ensuite:

HTML

<input type="text" name="one" class="two-digits"><br>
<input type="text" name="two" class="two-digits">​

jQuery

// apply the two-digits behaviour to elements with 'two-digits' as their class
$( function() {
    $('.two-digits').keyup(function(){
        if($(this).val().indexOf('.')!=-1){         
            if($(this).val().split(".")[1].length > 2){                
                if( isNaN( parseFloat( this.value ) ) ) return;
                this.value = parseFloat(this.value).toFixed(2);
            }  
         }            
         return this; //for chaining
    });
});

DÉMO EN LIGNE:

http://jsfiddle.net/c4Wqn/

vicaire
la source
1
Je peux apprécier la contribution, bien que je pense que l'ajout d'éléments DOM et de jQuery dans le mélange semble hors de portée de la question.
Chris May
Vous ne devez pas écouter l'événement keyup, car il semble très mauvais et ne s'active pas lorsque vous ajoutez quelque chose avec un script. Je préfère écouter l' inputévénement. Cela ne crée pas d'effet de scintillement et se déclenche également lorsque vous accédez au terrain avec JS
Le 'nton
3

Le problème avec les valeurs à virgule flottante est qu'elles essaient de représenter une quantité infinie de valeurs (continues) avec une quantité fixe de bits. Donc, naturellement, il doit y avoir une perte de jeu et vous allez être mordu avec certaines valeurs.

Lorsqu'un ordinateur stocke 1.275 en tant que valeur à virgule flottante, il ne se souvient pas réellement s'il s'agissait de 1.275 ou 1.27499999999999993, ou même 1.27500000000000002. Ces valeurs devraient donner des résultats différents après avoir arrondi à deux décimales, mais elles ne le seront pas, car pour l'ordinateur, elles ont exactement la même apparence après avoir été stockées sous forme de valeurs à virgule flottante, et il n'y a aucun moyen de restaurer les données perdues. Tout calcul supplémentaire ne fera qu'accumuler une telle imprécision.

Donc, si la précision est importante, vous devez éviter les valeurs à virgule flottante dès le départ. Les options les plus simples consistent à

  • utiliser une bibliothèque dédiée
  • utiliser des chaînes pour stocker et transmettre les valeurs (accompagnées d'opérations sur les chaînes)
  • utilisez des entiers (par exemple, vous pourriez faire circuler le montant des centièmes de votre valeur réelle, par exemple le montant en cents au lieu du montant en dollars)

Par exemple, lorsque vous utilisez des entiers pour stocker le nombre de centièmes, la fonction de recherche de la valeur réelle est assez simple:

function descale(num, decimals) {
    var hasMinus = num < 0;
    var numString = Math.abs(num).toString();
    var precedingZeroes = '';
    for (var i = numString.length; i <= decimals; i++) {
        precedingZeroes += '0';
    }
    numString = precedingZeroes + numString;
    return (hasMinus ? '-' : '') 
        + numString.substr(0, numString.length-decimals) 
        + '.' 
        + numString.substr(numString.length-decimals);
}

alert(descale(127, 2));

Avec les chaînes, vous aurez besoin d'arrondir, mais c'est toujours gérable:

function precise_round(num, decimals) {
    var parts = num.split('.');
    var hasMinus = parts.length > 0 && parts[0].length > 0 && parts[0].charAt(0) == '-';
    var integralPart = parts.length == 0 ? '0' : (hasMinus ? parts[0].substr(1) : parts[0]);
    var decimalPart = parts.length > 1 ? parts[1] : '';
    if (decimalPart.length > decimals) {
        var roundOffNumber = decimalPart.charAt(decimals);
        decimalPart = decimalPart.substr(0, decimals);
        if ('56789'.indexOf(roundOffNumber) > -1) {
            var numbers = integralPart + decimalPart;
            var i = numbers.length;
            var trailingZeroes = '';
            var justOneAndTrailingZeroes = true;
            do {
                i--;
                var roundedNumber = '1234567890'.charAt(parseInt(numbers.charAt(i)));
                if (roundedNumber === '0') {
                    trailingZeroes += '0';
                } else {
                    numbers = numbers.substr(0, i) + roundedNumber + trailingZeroes;
                    justOneAndTrailingZeroes = false;
                    break;
                }
            } while (i > 0);
            if (justOneAndTrailingZeroes) {
                numbers = '1' + trailingZeroes;
            }
            integralPart = numbers.substr(0, numbers.length - decimals);
            decimalPart = numbers.substr(numbers.length - decimals);
        }
    } else {
        for (var i = decimalPart.length; i < decimals; i++) {
            decimalPart += '0';
        }
    }
    return (hasMinus ? '-' : '') + integralPart + (decimals > 0 ? '.' + decimalPart : '');
}

alert(precise_round('1.275', 2));
alert(precise_round('1.27499999999999993', 2));

Notez que cette fonction arrondit au plus proche, les liens loin de zéro , tandis que IEEE 754 recommande d'arrondir au plus proche, les liens à même comme comportement par défaut pour les opérations en virgule flottante. De telles modifications sont laissées en exercice au lecteur :)

Imre
la source
3

En voici un simple

function roundFloat(num,dec){
    var d = 1;
    for (var i=0; i<dec; i++){
        d += "0";
    }
    return Math.round(num * d) / d;
}

Utilisez comme alert(roundFloat(1.79209243929,4));

Jsfiddle

ow3n
la source
2

Arrondissez votre valeur décimale, puis utilisez toFixed(x)pour vos chiffres attendus.

function parseDecimalRoundAndFixed(num,dec){
  var d =  Math.pow(10,dec);
  return (Math.round(num * d) / d).toFixed(dec);
}

Appel

parseDecimalRoundAndFixed (10.800243929,4) => 10.80 parseDecimalRoundAndFixed (10.807243929,2) => 10.81

HATCHA
la source
2

Arrondir vers le bas

function round_down(value, decPlaces) {
    return Math.floor(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}

Rassembler

function round_up(value, decPlaces) {
    return Math.ceil(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}

Arrondi le plus proche

function round_nearest(value, decPlaces) {
    return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}

Fusionné https://stackoverflow.com/a/7641824/1889449 et https://www.kirupa.com/html5/rounding_numbers_in_javascript.htm Merci.

MERT DOĞAN
la source
2

/**
 * MidpointRounding away from zero ('arithmetic' rounding)
 * Uses a half-epsilon for correction. (This offsets IEEE-754
 * half-to-even rounding that was applied at the edge cases).
 */

function RoundCorrect(num, precision = 2) {
	// half epsilon to correct edge cases.
	var c = 0.5 * Number.EPSILON * num;
//	var p = Math.pow(10, precision); //slow
	var p = 1; while (precision--> 0) p *= 10;
	if (num < 0)
		p *= -1;
	return Math.round((num + c) * p) / p;
}

// testing some +ve edge cases
console.log(RoundCorrect(1.005, 2));  // 1.01 correct
console.log(RoundCorrect(2.175, 2));  // 2.18 correct
console.log(RoundCorrect(5.015, 2));  // 5.02 correct

// testing some -ve edge cases
console.log(RoundCorrect(-1.005, 2));  // -1.01 correct
console.log(RoundCorrect(-2.175, 2));  // -2.18 correct
console.log(RoundCorrect(-5.015, 2));  // -5.02 correct

Amr Ali
la source
2

Voici ma solution 1 ligne: Number((yourNumericValueHere).toFixed(2));

Voici ce qui se passe:

1) Tout d'abord, vous appliquez .toFixed(2)sur le nombre dont vous souhaitez arrondir les décimales. Notez que cela convertira la valeur en une chaîne de nombre. Donc, si vous utilisez Typescript, cela générera une erreur comme celle-ci:

"Le type 'chaîne' n'est pas attribuable au type 'nombre'"

2) Pour récupérer la valeur numérique ou pour convertir la chaîne en valeur numérique, appliquez simplement la Number()fonction à cette valeur dite de "chaîne".

Pour des éclaircissements, regardez l'exemple ci-dessous:

EXEMPLE: J'ai un montant qui a jusqu'à 5 chiffres dans les décimales et je voudrais le raccourcir jusqu'à 2 décimales. Je le fais comme ça:

var price = 0.26453;
var priceRounded = Number((price).toFixed(2));
console.log('Original Price: ' + price);
console.log('Price Rounded: ' + priceRounded);

Devner
la source
1

Mettez les éléments suivants dans une portée globale:

Number.prototype.getDecimals = function ( decDigCount ) {
   return this.toFixed(decDigCount);
}

et puis essayer :

var a = 56.23232323;
a.getDecimals(2); // will return 56.23

Mise à jour

Notez que toFixed()cela ne peut fonctionner que pour le nombre de décimales entre 0-20ie a.getDecimals(25)peut générer une erreur javascript, donc pour accommoder que vous pouvez ajouter une vérification supplémentaire ie

Number.prototype.getDecimals = function ( decDigCount ) {
   return ( decDigCount > 20 ) ? this : this.toFixed(decDigCount);
}
Kamran Ahmed
la source
1
Number(((Math.random() * 100) + 1).toFixed(2))

cela renverra un nombre aléatoire de 1 à 100 arrondi à 2 décimales.

Johnathan Ralls
la source
1

Utilisation de cette réponse par référence: https://stackoverflow.com/a/21029698/454827

Je construis une fonction pour obtenir des nombres dynamiques de décimales:

function toDec(num, dec)
{
        if(typeof dec=='undefined' || dec<0)
                dec = 2;

        var tmp = dec + 1;
        for(var i=1; i<=tmp; i++)
                num = num * 10;

        num = num / 10;
        num = Math.round(num);
        for(var i=1; i<=dec; i++)
                num = num / 10;

        num = num.toFixed(dec);

        return num;
}

ici exemple de travail: https://jsfiddle.net/wpxLduLc/

ZiTAL
la source
1

parse = function (data) {
       data = Math.round(data*Math.pow(10,2))/Math.pow(10,2);
       if (data != null) {
            var lastone = data.toString().split('').pop();
            if (lastone != '.') {
                 data = parseFloat(data);
            }
       }
       return data;
  };

$('#result').html(parse(200)); // output 200
$('#result1').html(parse(200.1)); // output 200.1
$('#result2').html(parse(200.10)); // output 200.1
$('#result3').html(parse(200.109)); // output 200.11
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="result"></div>
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>

Vishnu T Asok
la source
1

Avec ces exemples, vous obtiendrez toujours une erreur lorsque vous essayez d'arrondir le nombre 1.005, la solution consiste à utiliser une bibliothèque comme Math.js ou cette fonction:

function round(value: number, decimals: number) {
    return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}
David Webster
la source
1

J'ai eu quelques idées de ce post il y a quelques mois, mais aucune des réponses ici, ni les réponses d'autres posts / blogs n'ont pu gérer tous les scénarios (par exemple, les nombres négatifs et certains "numéros porte-bonheur" trouvés par notre testeur). Au final, notre testeur n'a trouvé aucun problème avec cette méthode ci-dessous. Coller un extrait de mon code:

fixPrecision: function (value) {
    var me = this,
        nan = isNaN(value),
        precision = me.decimalPrecision;

    if (nan || !value) {
        return nan ? '' : value;
    } else if (!me.allowDecimals || precision <= 0) {
        precision = 0;
    }

    //[1]
    //return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
    precision = precision || 0;
    var negMultiplier = value < 0 ? -1 : 1;

    //[2]
    var numWithExp = parseFloat(value + "e" + precision);
    var roundedNum = parseFloat(Math.round(Math.abs(numWithExp)) + 'e-' + precision) * negMultiplier;
    return parseFloat(roundedNum.toFixed(precision));
},

J'ai aussi des commentaires sur le code (désolé, j'ai déjà oublié tous les détails) ... Je poste ma réponse ici pour référence future:

9.995 * 100 = 999.4999999999999
Whereas 9.995e2 = 999.5
This discrepancy causes Math.round(9.995 * 100) = 999 instead of 1000.
Use e notation instead of multiplying /dividing by Math.Pow(10,precision).
remondo
la source
0

Je résous le problème du modificateur. Prise en charge de 2 décimales uniquement.

$(function(){
  //input number only.
  convertNumberFloatZero(22); // output : 22.00
  convertNumberFloatZero(22.5); // output : 22.50
  convertNumberFloatZero(22.55); // output : 22.55
  convertNumberFloatZero(22.556); // output : 22.56
  convertNumberFloatZero(22.555); // output : 22.55
  convertNumberFloatZero(22.5541); // output : 22.54
  convertNumberFloatZero(22222.5541); // output : 22,222.54

  function convertNumberFloatZero(number){
	if(!$.isNumeric(number)){
		return 'NaN';
	}
	var numberFloat = number.toFixed(3);
	var splitNumber = numberFloat.split(".");
	var cNumberFloat = number.toFixed(2);
	var cNsplitNumber = cNumberFloat.split(".");
	var lastChar = splitNumber[1].substr(splitNumber[1].length - 1);
	if(lastChar > 0 && lastChar < 5){
		cNsplitNumber[1]--;
	}
	return Number(splitNumber[0]).toLocaleString('en').concat('.').concat(cNsplitNumber[1]);
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

bamossza
la source
0
(Math.round((10.2)*100)/100).toFixed(2)

Cela devrait donner: 10.20

(Math.round((.05)*100)/100).toFixed(2)

Cela devrait donner: 0.05

(Math.round((4.04)*100)/100).toFixed(2)

Cela devrait donner: 4.04

etc.

Anthony Ruffino
la source
0

/*Due to all told stuff. You may do 2 things for different purposes:
When showing/printing stuff use this in your alert/innerHtml= contents:
YourRebelNumber.toFixed(2)*/

var aNumber=9242.16;
var YourRebelNumber=aNumber-9000;
alert(YourRebelNumber);
alert(YourRebelNumber.toFixed(2));

/*and when comparing use:
Number(YourRebelNumber.toFixed(2))*/

if(YourRebelNumber==242.16)alert("Not Rounded");
if(Number(YourRebelNumber.toFixed(2))==242.16)alert("Rounded");

/*Number will behave as you want in that moment. After that, it'll return to its defiance.
*/

Christian Læirbag
la source
0

Ceci est très simple et fonctionne aussi bien que les autres:

function parseNumber(val, decimalPlaces) {
    if (decimalPlaces == null) decimalPlaces = 0
    var ret = Number(val).toFixed(decimalPlaces)
    return Number(ret)
}

Étant donné que toFixed () ne peut être appelé que sur des nombres et renvoie malheureusement une chaîne, cela effectue toute l'analyse pour vous dans les deux sens. Vous pouvez passer une chaîne ou un nombre, et vous obtenez un numéro à chaque fois! L'appel de parseNumber (1.49) vous donnera 1, et parseNumber (1.49,2) vous donnera 1,50. Tout comme les meilleurs d'entre eux!

Aaron Dake
la source
0

Vous pouvez également utiliser la .toPrecision()méthode et du code personnalisé et toujours arrondir au nième chiffre décimal quelle que soit la longueur de la partie int.

function glbfrmt (number, decimals, seperator) {
    return typeof number !== 'number' ? number : number.toPrecision( number.toString().split(seperator)[0].length + decimals);
}

Vous pouvez également en faire un plugin pour une meilleure utilisation.

leo_lo
la source
-1

Aussi simple que cela.

var rounded_value=Math.round(value * 100) / 100;
Gihan Gamage
la source
1
Faux. Essayez 1.015
Marco Marsala
-2

J'ai trouvé un moyen très simple qui a résolu ce problème pour moi et peut être utilisé ou adapté:

td[row].innerHTML = price.toPrecision(price.toFixed(decimals).length

la source
-4

100% de travail !!! Essayez-le

<html>
     <head>
      <script>
      function replacePonto(){
        var input = document.getElementById('qtd');
        var ponto = input.value.split('.').length;
        var slash = input.value.split('-').length;
        if (ponto > 2)
                input.value=input.value.substr(0,(input.value.length)-1);

        if(slash > 2)
                input.value=input.value.substr(0,(input.value.length)-1);

        input.value=input.value.replace(/[^0-9.-]/,'');

        if (ponto ==2)
	input.value=input.value.substr(0,(input.value.indexOf('.')+3));

if(input.value == '.')
	input.value = "";
              }
      </script>
      </head>
      <body>
         <input type="text" id="qtd" maxlength="10" style="width:140px" onkeyup="return replacePonto()">
      </body>
    </html>

JONAS MAGALHAES DOS SANTOS
la source
Bienvenue chez SO. Veuillez lire ce tutoriel et suivre les instructions pour répondre.
thewaywewere