Come formattare un float in javascript?


427

In JavaScript, quando si converte da un float a una stringa, come posso ottenere solo 2 cifre dopo il punto decimale? Ad esempio, 0,34 anziché 0,3445434.


16
Solo un po 'di nit-pick: vuoi' tagliare 'tutto tranne le prime due cifre, o vuoi arrotondare a due cifre?
xtofl

Risposte:


232
var result = Math.round(original*100)/100;

Le specifiche , nel caso in cui il codice non sia autoesplicativo.

modifica: ... o semplicemente usa toFixed, come proposto da Tim Büthe . Dimenticato quello, grazie (e un voto) per il promemoria :)


1
Lo stavo usando nella libreria "Highchart" dove non accetta i valori di stringa, quindi toFixed non ha funzionato per me, Math.round ha risolto il mio problema, grazie
Swapnil Chincholkar,

4
toFixed()imiterà ciò che printf()fa qualcosa di simile in C. Tuttavia, toFixed()e Math.round()gestirà l'arrotondamento in modo diverso. In questo caso, toFixed()avrà lo stesso tipo di effetto che Math.floor()avrebbe (garantito che stai moltiplicando in anticipo l'originale di 10 ^ n e chiamando toFixed()con n cifre). La "correttezza" della risposta dipende molto da ciò che l'OP vuole qui, ed entrambi sono "corretti" a modo loro.
DDPWNAGE,

838

Ci sono funzioni per arrotondare i numeri. Per esempio:

var x = 5.0364342423;
print(x.toFixed(2));

stamperà 5.04.

EDIT: violino


7
Vorrei sconsigliare di usare print () in un browser
cobbal

70
Fai attenzione a questo, toFixed () restituisce una stringa: var x = 5.036432346; var y = x.toFixed(2) + 100; ysarà uguale"5.03100"
Vlad

5
Ricorda che (1e100) .toFixed (2) === "1e + 100"
qbolec,

7
Inoltre, (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)
fai

3
Se cerchi un equivalente di ToFixed ma con arrotondamento costante, usa toLocaleString: (0.345) .toLocaleString ('en-EN', {minimumFractionDigits: 2, maximumFractionDigits: 2})
fred727

185

Fai attenzione quando usi toFixed():

Innanzitutto, l'arrotondamento del numero viene eseguito utilizzando la rappresentazione binaria del numero, che potrebbe portare a comportamenti imprevisti. Per esempio

(0.595).toFixed(2) === '0.59'

invece di '0.6'.

In secondo luogo, c'è un bug IE con toFixed(). In IE (almeno fino alla versione 7, non ho verificato IE8), vale quanto segue:

(0.9).toFixed(0) === '0'

Potrebbe essere una buona idea seguire il suggerimento di Kkyy o utilizzare una toFixed()funzione personalizzata , ad es

function toFixed(value, precision) {
    var power = Math.pow(10, precision || 0);
    return String(Math.round(value * power) / power);
}

Sì, questo può essere molto importante quando si crea un codice per prevedere i prezzi. Grazie! +1
Fabio Milheiro,

10
Suggerirei di aggiungere il .toFixed()metodo nativo nel valore restituito, che aggiungerà la quantità richiesta di precisione, ad esempio: return (Math.round(value * power) / power).toFixed(precision);e restituirà anche il valore come stringa. Altrimenti, la precisione di 20 viene ignorata per i decimali più piccoli
William Joss Crowcroft,

3
Una nota riguardante toFixed: nota che aumentare la precisione può produrre risultati inaspettati:, (1.2).toFixed(16) === "1.2000000000000000"mentre (1.2).toFixed(17) === "1.19999999999999996"(in Firefox / Chrome; in IE8 quest'ultimo non regge a causa della minore precisione che IE8 può offrire internamente).
jakub.g,

2
Si prega di notare che anche (0.598).toFixed(2)non produce 0.6. Produce 0.60:)
qbolec il

1
Inoltre, fate attenzione dell'arrotondamento inconstistent: (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2).
Skippy le Grand Gourou,

36

Un altro problema da tenere presente è che toFixed()può produrre zeri non necessari alla fine del numero. Per esempio:

var x=(23-7.37)
x
15.629999999999999
x.toFixed(6)
"15.630000"

L'idea è di ripulire l'output usando un RegExp:

function humanize(x){
  return x.toFixed(6).replace(/\.?0*$/,'');
}

Il RegExppartite le zeri finali (e facoltativamente il punto decimale) per assicurarsi che si guarda bene per gli interi pure.

humanize(23-7.37)
"15.63"
humanize(1200)
"1200"
humanize(1200.03)
"1200.03"
humanize(3/4)
"0.75"
humanize(4/3)
"1.333333"

Number.prototype.minFixed = function (decimals) {return this.toFixed (decimals) .replace (/ \.? 0 * $ /, ""); }
Luc Bloom,

Questo dovrebbe essere accettato, gli zeri finali sono fastidiosi, stavo cercando esattamente questa soluzione, gj.
exoslav,

1
Gli zeri finali possono essere fastidiosi, ma questo è esattamente ciò che il nome del metodo "toFixed" promette di fare;)
ksadowski

11
var x = 0.3445434
x = Math.round (x*100) / 100 // this will make nice rounding

Math.round (1.015 * 100) / 100 dà 1,01 mentre ci aspetteremmo che sia 1,02?
gaurav5430,

6

C'è un problema con tutte quelle soluzioni che fluttuano intorno usando i moltiplicatori. Sfortunatamente sia la soluzione di Kkyy che quella di Christoph sono sbagliate.

Si prega di testare il codice per il numero 551.175 con 2 cifre decimali: arrotonderà a 551,17 mentre dovrebbe essere 551,18 ! Ma se provi per es. 451.175 andrà bene - 451.18. Quindi è difficile individuare questo errore a prima vista.

Il problema è con la moltiplicazione: prova 551.175 * 100 = 55117.49999999999 (aumenta!)

Quindi la mia idea è di trattarlo con toFixed () prima di usare Math.round ();

function roundFix(number, precision)
{
    var multi = Math.pow(10, precision);
    return Math.round( (number * multi).toFixed(precision + 1) ) / multi;
}

1
Questo è il problema con l'aritmetica in js: (551.175 * 10 * 10)! == (551.175 * 100). Devi usare incrementi decimali per spostare la virgola per risultati decimali non reali.
Kir Kanos,

+1 per aver notato questo, tuttavia toFixedè anche influenzato - (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)... Qualunque sia il metodo utilizzato, è meglio aggiungere un epsilon prima dell'arrotondamento.
Skippy le Grand Gourou,

5

La chiave qui credo sia di arrotondare prima correttamente, quindi puoi convertirla in String.

function roundOf(n, p) {
    const n1 = n * Math.pow(10, p + 1);
    const n2 = Math.floor(n1 / 10);
    if (n1 >= (n2 * 10 + 5)) {
        return (n2 + 1) / Math.pow(10, p);
    }
    return n2 / Math.pow(10, p);
}

// All edge cases listed in this thread
roundOf(95.345, 2); // 95.35
roundOf(95.344, 2); // 95.34
roundOf(5.0364342423, 2); // 5.04
roundOf(0.595, 2); // 0.60
roundOf(0.335, 2); // 0.34
roundOf(0.345, 2); // 0.35
roundOf(551.175, 2); // 551.18
roundOf(0.3445434, 2); // 0.34

Ora puoi formattare in modo sicuro questo valore con toFixed (p). Quindi con il tuo caso specifico:

roundOf(0.3445434, 2).toFixed(2); // 0.34

3

Se vuoi la stringa senza giro puoi usare questo RegEx (forse non è il modo più efficiente ... ma è davvero facile)

(2.34567778).toString().match(/\d+\.\d{2}/)[0]
// '2.34'

1
function trimNumber(num, len) {
  const modulu_one = 1;
  const start_numbers_float=2;
  var int_part = Math.trunc(num);
  var float_part = String(num % modulu_one);
      float_part = float_part.slice(start_numbers_float, start_numbers_float+len);
  return int_part+'.'+float_part;
}

ottima risposta, tranne per il fatto che mancano i punti e virgola (No, in sei punti i punti e virgola non sono obsoleti e in alcuni casi dobbiamo ancora usarli). Ho dovuto anche modificare ultima fila a: return float_part ? int_part+'.'+float_part : int_part;altrimenti se hai superato Integer, è tornato il numero con un punto alla fine (ad esempio ingresso: 2100, uscita: 2100.)
Kuba Simonovsky

0

Forse vorrai anche un separatore decimale? Ecco una funzione che ho appena fatto:

function formatFloat(num,casasDec,sepDecimal,sepMilhar) {
    if (num < 0)
    {
        num = -num;
        sinal = -1;
    } else
        sinal = 1;
    var resposta = "";
    var part = "";
    if (num != Math.floor(num)) // decimal values present
    {
        part = Math.round((num-Math.floor(num))*Math.pow(10,casasDec)).toString(); // transforms decimal part into integer (rounded)
        while (part.length < casasDec)
            part = '0'+part;
        if (casasDec > 0)
        {
            resposta = sepDecimal+part;
            num = Math.floor(num);
        } else
            num = Math.round(num);
    } // end of decimal part
    while (num > 0) // integer part
    {
        part = (num - Math.floor(num/1000)*1000).toString(); // part = three less significant digits
        num = Math.floor(num/1000);
        if (num > 0)
            while (part.length < 3) // 123.023.123  if sepMilhar = '.'
                part = '0'+part; // 023
        resposta = part+resposta;
        if (num > 0)
            resposta = sepMilhar+resposta;
    }
    if (sinal < 0)
        resposta = '-'+resposta;
    return resposta;
}

0

Non è possibile evitare arrotondamenti incoerenti per i prezzi con x.xx5 come valore effettivo utilizzando la moltiplicazione o la divisione. Se è necessario calcolare i prezzi corretti sul lato client, è necessario conservare tutti gli importi in centesimi. Ciò è dovuto alla natura della rappresentazione interna dei valori numerici in JavaScript. Si noti che Excel soffre degli stessi problemi, quindi la maggior parte delle persone non noterebbe i piccoli errori causati da questo fenomeno. Tuttavia, gli errori possono accumularsi ogni volta che si sommano molti valori calcolati, c'è un'intera teoria attorno a ciò che coinvolge l'ordine dei calcoli e altri metodi per minimizzare l'errore nel risultato finale. Per enfatizzare i problemi con i valori decimali, si noti che 0,1 + 0,2 non è esattamente uguale a 0,3 in JavaScript, mentre 1 + 2 è uguale a 3.


la soluzione sarebbe quella di separare l'intera parte e la parte decimale e rappresentarle come numeri interi nella base 10, invece di usare i float, qui funziona senza problemi per prettyPrint, ma in generale devi scegliere tra una base e un'altra, una rappresentazione per numeri reali e un altro, ognuno ha i suoi problemi
repliche

"Excel soffre degli stessi problemi". fonte ?
gaurav5430,

0
/** don't spend 5 minutes, use my code **/
function prettyFloat(x,nbDec) { 
    if (!nbDec) nbDec = 100;
    var a = Math.abs(x);
    var e = Math.floor(a);
    var d = Math.round((a-e)*nbDec); if (d == nbDec) { d=0; e++; }
    var signStr = (x<0) ? "-" : " ";
    var decStr = d.toString(); var tmp = 10; while(tmp<nbDec && d*tmp < nbDec) {decStr = "0"+decStr; tmp*=10;}
    var eStr = e.toString();
    return signStr+eStr+"."+decStr;
}

prettyFloat(0);      //  "0.00"
prettyFloat(-1);     // "-1.00"
prettyFloat(-0.999); // "-1.00"
prettyFloat(0.5);    //  "0.50"

0

Uso questo codice per formattare i float. Si basa su toPrecision()ma elimina gli zeri non necessari. Gradirei suggerimenti su come semplificare la regex.

function round(x, n) {
    var exp = Math.pow(10, n);
    return Math.floor(x*exp + 0.5)/exp;
}

Esempio di utilizzo:

function test(x, n, d) {
    var rounded = rnd(x, d);
    var result = rounded.toPrecision(n);
    result = result.replace(/\.?0*$/, '');
    result = result.replace(/\.?0*e/, 'e');
    result = result.replace('e+', 'e');
    return result;  
}

document.write(test(1.2000e45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2000e+45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2340e45, 3, 2) + '=' + '1.23e45' + '<br>');
document.write(test(1.2350e45, 3, 2) + '=' + '1.24e45' + '<br>');
document.write(test(1.0000, 3, 2) + '=' + '1' + '<br>');
document.write(test(1.0100, 3, 2) + '=' + '1.01' + '<br>');
document.write(test(1.2340, 4, 2) + '=' + '1.23' + '<br>');
document.write(test(1.2350, 4, 2) + '=' + '1.24' + '<br>');
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.