Javascript, toFixed un decimale tranne quando è 0

Oct 09 2020

Devo correggere un numero con decimali a solo 1 decimale, quindi ho provato questo:

const convert = (numberWithDecimal) => numberWithDecimal
  .toFixed(1)
  .replace('.', ',')
  .replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1.");

console.log(convert(123.123)); // "123,1" that's ok
console.log(convert(123.005)); // "123,0" that's NOT ok

Il codice è qui: https://jsfiddle.net/pmiranda/sp0fLrhb/3/ Ma, quando i decimali sono arrotondati a 0, non voglio usarlo, ad esempio:

In 123.005ho bisogno di ottenere 123, non123.0

Qualsiasi aiuto?

Risposte

2 stevendesu Oct 09 2020 at 18:18

L'intero scopo della .toFixedfunzione è garantire un numero fisso di cifre decimali, ad esempio quando si visualizza la valuta (spesso si visualizzano$25.00 instead of $25)

Se non vuoi un numero fisso di punti decimali (ad esempio, a volte vuoi 0 ea volte vuoi 1), allora non vuoi usare .toFixed. Prova invece a utilizzare la moltiplicazione e l'arrotondamento per ottenere il risultato desiderato:

const convert = (numberWithDecimal) => String(
        Math.round(numberWithDecimal * 10) / 10
    )
    .replace(".", ",");
console.log(convert(123.123));
console.log(convert(123.005));

Una nota interessante sulla performance

Mi piace al profilo soluzioni quando possibile e sembrava a prima vista come la mia soluzione sarebbe più veloce (sto solo eseguendo qualche intero aritmetica, mentre si sta eseguendo molteplici funzioni stringa). Quindi ho scritto quanto segue:

var d0 = new Date();
for (var i = 0; i < 1000000; i++) { convert(123.123); }
console.log(new Date() - d0);

Ho quindi testato le nostre due soluzioni. Sulla mia macchina la tua soluzione ha funzionato circa il 15% più velocemente della mia. Non so perché, ma se sei interessato alle massime prestazioni, la tua soluzione di più .replace()catene in realtà è stata eseguita più velocemente (in Firefox su Mac OS X)

Nota 2 sulle prestazioni

Se scegli di utilizzare la Math.round()soluzione ma desideri che venga eseguita un po ' più velocemente, c'è un hack in JavaScript per arrotondare i numeri molto velocemente:

Math.round(123.123); // 123
Math.round(123.987); // 124

(123.123 + 0.5)|0; // 123
(123.987 + 0.5)|0; // 124

Nota che questo hack in realtà fallisce con numeri negativi. Ma fintanto che hai a che fare con numeri positivi, questo metodo è più veloce della chiamata Math.round()(e ottiene prestazioni alla pari con la tua soluzione

Funziona perché gli operatori bit a bit in JavaScript ( &, |, ^, ~) funzionano solo su interi valori. Se viene passato un numero non intero, tronceranno prima il valore (eliminando eventuali punti decimali). Dato che vogliamo arrotondare e non troncare, aggiungiamo 0,5 prima del troncamento.

1 imvain2 Oct 09 2020 at 18:17

Immagino che l'ovvia soluzione semplice sia aggiungere replace(',0','')alla catena.

const convert = (numberWithDecimal) => numberWithDecimal
  .toFixed(1)
  .replace('.', ',')
  .replace(',0', '')
  .replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1.");

console.log(convert(123.123)); // "123,1" that's ok
console.log(convert(123.005)); // "123,1" that's ok