javascript - places - node js round to integer




Arrotondati al massimo a 2 posizioni decimali(solo se necessario) (20)

Mi piacerebbe arrotondare al massimo 2 posizioni decimali, ma solo se necessario .

Ingresso:

10
1.7777777
9.1

Produzione:

10
1.78
9.1

Come posso farlo in JavaScript ?


2017
Basta usare il codice nativo .toFixed()

number = 1.2345;
number.toFixed(2) // "1.23"

Se è necessario essere severi e aggiungere cifre solo se necessario, è possibile utilizzare replace

number = 1; // "1"
number.toFixed(5).replace(/\.?0*$/g,'');


Ecco un modo semplice per farlo:

Math.round(value * 100) / 100

Potresti voler andare avanti e creare una funzione separata per farlo per te:

function roundToTwo(value) {
    return(Math.round(value * 100) / 100);
}

Quindi devi semplicemente passare il valore.

Potresti potenziarlo per arrotondare a qualsiasi numero arbitrario di decimali aggiungendo un secondo parametro.

function myRound(value, places) {
    var multiplier = Math.pow(10, places);

    return (Math.round(value * multiplier) / multiplier);
}

Il modo più semplice:

+num.toFixed(2)

Lo converte in una stringa, e poi di nuovo in un intero / float.


Prova questa soluzione leggera :

function round(x, digits){
  return parseFloat(x.toFixed(digits))
}

 round(1.222,  2) ;
 // 1.22
 round(1.222, 10) ;
 // 1.222

Puoi usare

function roundToTwo(num) {    
    return +(Math.round(num + "e+2")  + "e-2");
}

L'ho trovato su MDN . La loro strada evita il problema con 1.005 che è stato mentioned .

roundToTwo(1.005)
1.01
roundToTwo(10)
10
roundToTwo(1.7777777)
1.78
roundToTwo(9.1)
9.1
roundToTwo(1234.5678)
1234.57


Se il valore è un tipo di testo:

parseFloat("123.456").toFixed(2);

Se il valore è un numero:

var numb = 123.23454;
numb = numb.toFixed(2);

C'è un lato negativo che valori come 1.5 daranno "1.50" come output. Una correzione suggerita da @minitech:

var numb = 1.5;
numb = +numb.toFixed(2);
// Note the plus sign that drops any "extra" zeroes at the end.
// It changes the result (which is a string) into a number again (think "0 + foo"),
// which means that it uses only as many digits as necessary.

Sembra che Math.round sia una soluzione migliore. Ma non è! In alcuni casi NON arrotonda correttamente:

Math.round(1.005 * 1000)/1000 // Returns 1 instead of expected 1.01!

toFixed () inoltre NON arrotonderà correttamente in alcuni casi (testato in Chrome v.55.0.2883.87)!

Esempi:

parseFloat("1.555").toFixed(2); // Returns 1.55 instead of 1.56.
parseFloat("1.5550").toFixed(2); // Returns 1.55 instead of 1.56.
// However, it will return correct result if you round 1.5551.
parseFloat("1.5551").toFixed(2); // Returns 1.56 as expected.

1.3555.toFixed(3) // Returns 1.355 instead of expected 1.356.
// However, it will return correct result if you round 1.35551.
1.35551.toFixed(2); // Returns 1.36 as expected.

Immagino, questo è perché 1.555 è in realtà qualcosa come float 1.55499994 dietro le quinte.

La soluzione 1 consiste nell'utilizzare uno script con l'algoritmo di arrotondamento richiesto, ad esempio:

function roundNumber(num, scale) {
  if(!("" + num).includes("e")) {
    return +(Math.round(num + "e+" + scale)  + "e-" + scale);
  } else {
    var arr = ("" + num).split("e");
    var sig = ""
    if(+arr[1] + scale > 0) {
      sig = "+";
    }
    return +(Math.round(+arr[0] + "e" + sig + (+arr[1] + scale)) + "e-" + scale);
  }
}

https://plnkr.co/edit/uau8BlS1cqbvWPCHJeOy?p=preview

La soluzione 2 è di evitare calcoli front-end e di ottenere valori arrotondati dal server di back-end.


Un preciso metodo di arrotondamento. Fonte: MDN

(function(){

    /**
     * Decimal adjustment of a number.
     *
     * @param   {String}    type    The type of adjustment.
     * @param   {Number}    value   The number.
     * @param   {Integer}   exp     The exponent (the 10 logarithm of the adjustment base).
     * @returns {Number}            The adjusted value.
     */
    function decimalAdjust(type, value, exp) {
        // If the exp is undefined or zero...
        if (typeof exp === 'undefined' || +exp === 0) {
            return Math[type](value);
        }
        value = +value;
        exp = +exp;
        // If the value is not a number or the exp is not an integer...
        if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
            return NaN;
        }
        // Shift
        value = value.toString().split('e');
        value = Math[type](+(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));
    }

    // Decimal round
    if (!Math.round10) {
        Math.round10 = function(value, exp) {
            return decimalAdjust('round', value, exp);
        };
    }
    // Decimal floor
    if (!Math.floor10) {
        Math.floor10 = function(value, exp) {
            return decimalAdjust('floor', value, exp);
        };
    }
    // Decimal ceil
    if (!Math.ceil10) {
        Math.ceil10 = function(value, exp) {
            return decimalAdjust('ceil', value, exp);
        };
    }
})();

Esempi:

// Round
Math.round10(55.55, -1); // 55.6
Math.round10(55.549, -1); // 55.5
Math.round10(55, 1); // 60
Math.round10(54.9, 1); // 50
Math.round10(-55.55, -1); // -55.5
Math.round10(-55.551, -1); // -55.6
Math.round10(-55, 1); // -50
Math.round10(-55.1, 1); // -60
Math.round10(1.005, -2); // 1.01 -- compare this with Math.round(1.005*100)/100 above
// Floor
Math.floor10(55.59, -1); // 55.5
Math.floor10(59, 1); // 50
Math.floor10(-55.51, -1); // -55.6
Math.floor10(-51, 1); // -60
// Ceil
Math.ceil10(55.51, -1); // 55.6
Math.ceil10(51, 1); // 60
Math.ceil10(-55.59, -1); // -55.5
Math.ceil10(-59, 1); // -50

Usa Math.round(num * 100) / 100


Ecco un metodo prototipo:

Number.prototype.round = function(places){
    places = Math.pow(10, places); 
    return Math.round(this * places)/places;
}

var yournum = 10.55555;
yournum = yournum.round(2);

In generale, l'arrotondamento viene eseguito mediante ridimensionamento: round(num / p) * p

L'uso della notazione esponenziale gestisce l'arrotondamento dei numeri + ve, correttamente. Tuttavia, questo metodo non riesce a arrotondare correttamente i casi limite.

function round(num, precision = 2) {
	var scaled = Math.round(num + "e" + precision);
	return Number(scaled + "e" + -precision);
}

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

console.log( round(-1.005, 2) );  // -1    wrong
console.log( round(-2.175, 2) );  // -2.17 wrong
console.log( round(-5.015, 2) );  // -5.01 wrong

Qui, c'è anche una funzione che ho scritto per fare correttamente l'arrotondamento aritmetico. Puoi testarlo da solo.

/**
 * 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 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

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



Se stai usando la libreria di lodash, puoi usare il metodo round di lodash come segue.

_.round(number, precision)

Per esempio:

_.round(1.7777777, 2) = 1.78

Usa qualcosa come questo "parseFloat (parseFloat (valore) .toFixed (2))"

parseFloat(parseFloat("1.7777777").toFixed(2))-->1.78 
parseFloat(parseFloat("10").toFixed(2))-->10 
parseFloat(parseFloat("9.1").toFixed(2))-->9.1

Ci sono un paio di modi per farlo. Per le persone come me, la variante di Lodash

function round(number, precision) {
    var pair = (number + 'e').split('e')
    var value = Math.round(pair[0] + 'e' + (+pair[1] + precision))
    pair = (value + 'e').split('e')
    return +(pair[0] + 'e' + (+pair[1] - precision))
}

Uso:

round(0.015, 2) // 0.02
round(1.005, 2) // 1.01

Se il tuo progetto utilizza jQuery o lodash, puoi trovare anche il roundmetodo corretto nelle librerie.

Aggiornamento 1

Ho rimosso la variante n.toFixed(2), perché non è corretta. Grazie @ valanghe1


MarkG e Lavamantis hanno offerto una soluzione molto migliore di quella che è stata accettata. È un peccato che non ottengano più upvotes!

Ecco la funzione che utilizzo per risolvere i problemi dei decimali in virgola mobile anche in base a MDN . È ancora più generico (ma meno conciso) della soluzione di Lavamantis:

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

Usalo con:

round(10.8034, 2);      // Returns 10.8
round(1.275, 2);        // Returns 1.28
round(1.27499, 2);      // Returns 1.27
round(1.2345678e+2, 2); // Returns 123.46

Rispetto alla soluzione di Lavamantis, possiamo fare ...

round(1234.5678, -2); // Returns 1200
round("123.45");      // Returns 123

Per me MDN non stava dando una risposta corretta. Ho trovato toFixed funziona meglio. Di seguito sono riportati esempi di entrambi:

console.log(Math.round(43000 / 80000) * 100); // wrong answer

console.log(((43000 / 80000) * 100).toFixed(2)); // correct answer


Un modo per ottenere tale arrotondamento solo se necessario è utilizzare Number.prototype.toLocaleString() :

myNumber.toLocaleString('en', {maximumFractionDigits:2, useGrouping:false})

Ciò fornirà esattamente l'output che ti aspetti, ma come stringhe. Puoi ancora convertirli in numeri se non è il tipo di dati che ti aspetti.


+(10).toFixed(2); // = 10
+(10.12345).toFixed(2); // = 10.12

(10).toFixed(2); // = 10.00
(10.12345).toFixed(2); // = 10.12




decimal-point