Come arrotondare un numero in Javascript?


159

Voglio usare Javascript per arrotondare un numero. Dato che il numero è valuta, voglio arrotondare come in questi esempi (2 punti decimali):

  • 192.168 => 192.20
  • 192.11 => 192.20
  • 192.21 => 192.30
  • 192.26 => 192.30
  • 192.20 => 192.20

Come raggiungere questo obiettivo utilizzando Javascript? La funzione Javascript integrata arrotonda per eccesso il numero in base alla logica standard (sempre meno di 5 per arrotondare per eccesso).

Risposte:


313
/**
 * @param num The number to round
 * @param precision The number of decimal places to preserve
 */
function roundUp(num, precision) {
  precision = Math.pow(10, precision)
  return Math.ceil(num * precision) / precision
}

roundUp(192.168, 1) //=> 192.2

2
@AndrewMarshall qual è lo scopo di moltiplicare, quindi dividere per 10?
codecowboy

6
@codecowboy Se non lo fai, allora ceil()ti darà 193, quindi dobbiamo assicurarci che tutta la precisione che vogliamo mantenere sia prima del punto decimale. Quindi eseguiamo l'operazione inversa al fine di ripristinare il valore "originale".
Andrew Marshall,

1
Se ottieni un numero simile 192.19999999999997, puoi fare domanda .toFixed(1)pernum
flamer.ohr

4
E per quelli qui che si chiedono come arrotondare al numero INTERO più vicino, hai solo bisogno di Math.ceil (). Il resto è solo per gestire i decimali. Per salvare gli altri il tempo impiegato dal mio cervello per arrivare a quello!
Nigel B. Peck,

Questa soluzione presenta un bug: Math.ceil (0,0159 * 1000000000) / precision. Otterrai una frazione di 0,015900001. È necessario aggiungere una validazione dell'intervallo per la precisione.
Frank,

26

Poco tardi, ma è possibile creare una funzione javascript riutilizzabile per questo scopo:

// Arguments: number to round, number of decimal places
function roundNumber(rnum, rlength) { 
    var newnumber = Math.round(rnum * Math.pow(10, rlength)) / Math.pow(10, rlength);
    return newnumber;
}

Chiamare la funzione come

alert(roundNumber(192.168,2));

2
Funziona alla grande, ma l'OP ha chiesto come arrotondare un numero, quindi Math.ceil dovrebbe essere usato qui invece di Math.round.
kloddant,

Questa risposta è migliore della risposta accettata se stai cercando di arrotondare correttamente nonostante il decimale che stai mirando. Esempio: 1.054 -> 1.05 1.055 -> 1.06 TUTTAVIA ecco un caso limite: 1.005 -> 1 1.006 -> 1.01 E 1.015 -> 1.01 1.016 -> 1.02 Quindi fai attenzione.
Jay K

21

L'arrotondamento normale funzionerà con una piccola modifica:

Math.round(price * 10)/10

e se vuoi mantenere un formato valuta, puoi usare il metodo Numero .toFixed()

(Math.round(price * 10)/10).toFixed(2)

Anche se questo lo renderà una stringa =)


Math.round (192.11 * 100) / 100 -> 192.11
krtek

1
Il secondo non ha bisogno di arrotondamenti, è più simile aprice.toFixed(2)
Michael Krelin - l'hacker del

@Krtek ooops, grazie per averlo colto. Ho letto male la domanda. Risposta aggiornata
Shad

2
L'OP ha chiesto come arrotondare un numero, quindi Math.ceil dovrebbe essere usato qui invece di Math.round.
kloddant,

10

Molto vicino alla risposta di TheEye , ma cambio una piccola cosa per farlo funzionare:

var num = 192.16;
    
console.log(    Math.ceil(num * 10) / 10    );


2

Il PO si aspetta due cose:
A. arrotondare per eccesso ai decimi più alti e
B. per mostrare uno zero al centesimo posto (un bisogno tipico con la valuta).

Soddisfare entrambi i requisiti sembrerebbe richiedere un metodo separato per ciascuno dei precedenti. Ecco un approccio che si basa sulla risposta suggerita da suryakiran:

//Arguments: number to round, number of decimal places.

function roundPrice(rnum, rlength) {
    var newnumber = Math.ceil(rnum * Math.pow(10, rlength-1)) / Math.pow(10, rlength-1);
    var toTenths = newnumber.toFixed(rlength);
    return toTenths;
}

alert(roundPrice(678.91011,2)); // returns 679.00
alert(roundPrice(876.54321,2)); // returns 876.60

Nota importante: questa soluzione produce un risultato molto diverso con numeri negativi ed esponenziali.

Per motivi di confronto tra questa risposta e due molto simili, vedere i seguenti 2 approcci. Il primo arrotonda semplicemente al centesimo più vicino al solito, e il secondo arrotonda semplicemente al centesimo più vicino (più grande).

function roundNumber(rnum, rlength) { 
    var newnumber = Math.round(rnum * Math.pow(10, rlength)) / Math.pow(10, rlength);
    return newnumber;
}

alert(roundNumber(678.91011,2)); // returns 678.91

function ceilNumber(rnum, rlength) { 
    var newnumber = Math.ceil(rnum * Math.pow(10, rlength)) / Math.pow(10, rlength);
    return newnumber;
}

alert(ceilNumber(678.91011,2)); // returns 678.92

2

ok, questa è stata risposta, ma ho pensato che ti sarebbe piaciuto vedere la mia risposta che chiama una volta la funzione math.pow (). Immagino che mi piace mantenere le cose ASCIUTTE.

function roundIt(num, precision) {
    var rounder = Math.pow(10, precision);
    return (Math.round(num * rounder) / rounder).toFixed(precision)
};

In un certo senso mette tutto insieme. Sostituisci Math.round () con Math.ceil () per arrotondare invece di arrotondare, che è quello che l'OP voleva.


1

questa funzione limita i decimali senza numero rotondo

function limitDecimal(num,decimal){
     return num.toString().substring(0, num.toString().indexOf('.')) + (num.toString().substr(num.toString().indexOf('.'), decimal+1));
}

Come alternativa più breve: return ('' + num) .split ('.'). Shift ()
Roberto

grazie Roberto questo codice funziona, ma rimuovi tutti i decimali
Behnam Mohammadi,

0

Sto usando la risposta di @AndrewMarshall da molto tempo, ma ho trovato alcuni casi limite. I seguenti test non superano:

equals(roundUp(9.69545, 4), 9.6955);
equals(roundUp(37.760000000000005, 4), 37.76);
equals(roundUp(5.83333333, 4), 5.8333);

Ecco quello che ora uso per fare in modo che l'arrotondamento si comporti correttamente:

// Closure
(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;
    }
    // If the value is negative...
    if (value < 0) {
      return -decimalAdjust(type, -value, exp);
    }
    // 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);
    };
  }
})();

// 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
Math.round10(-1.005, -2);  // -1.01
// 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

Fonte: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round


1
I casi di test sembrano errati. roundUp(37.760000000000005, 4)dovrebbe essere 37.7601e roundUp(5.83333333, 4)dovrebbe essere 5.8334. Questi due (e il tuo primo) sono tutti validi per il fn che ho fornito.
Andrew Marshall,

@AndrewMarshall ha ragione, i valori previsti sono errati per i casi 2 e 3.
Amn

-3

analizza sempre arrotondando per difetto .....

console.log(parseInt(5.8)+1);

do parseInt () + 1

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.