Mi sto perdendo qualcosa qui?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Perché non.toFixed()
restituire una stringa?
Voglio arrotondare il numero a 2 cifre decimali.
Mi sto perdendo qualcosa qui?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Perché non.toFixed()
restituire una stringa?
Voglio arrotondare il numero a 2 cifre decimali.
Risposte:
Restituisce una stringa perché 0.1, e i suoi poteri (che sono usati per visualizzare le frazioni decimali), non sono rappresentabili (almeno non con la massima precisione) nei sistemi binari a virgola mobile.
Ad esempio, 0,1 è davvero 0,1000000000000000055511151231257827021181583404541015625 e 0,01 è davvero 0,010000000000000000008868681711721685132943093776702880859375. (Grazie per BigDecimal
aver dimostrato il mio punto. :-P)
Pertanto (in assenza di un virgola mobile decimale o di un tipo di numero razionale), emetterlo come una stringa è l'unico modo per farlo tagliare esattamente alla precisione richiesta per la visualizzazione.
toFixed
è una funzione di formattazione, che ha il solo scopo di convertire un numero in una stringa, formattandolo utilizzando il numero specificato di decimali. Il motivo per cui restituisce una stringa è perché dovrebbe restituire una stringa e se invece fosse stata nominata toStringFixed
, OP non sarebbe sorpreso dai risultati. L'unico problema qui è che OP si aspettava che funzionasse come Math.round
, senza consultare il riferimento JS.
Number.prototype.toFixed
è una funzione progettata per formattare un numero prima di stamparlo. Viene dalla famiglia di toString
, toExponential
e toPrecision
.
Per arrotondare un numero, devi fare questo:
someNumber = 42.008;
someNumber = Math.round( someNumber * 1e2 ) / 1e2;
someNumber === 42.01;
// if you need 3 digits, replace 1e2 with 1e3 etc.
// or just copypaste this function to your code:
function toFixedNumber(num, digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(num*pow) / pow;
}
.
Oppure, se si desidera una funzione " simile al nativo ", è possibile estendere il prototipo:
Number.prototype.toFixedNumber = function(digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(this*pow) / pow;
}
someNumber = 42.008;
someNumber = someNumber.toFixedNumber(2);
someNumber === 42.01;
//or even hexadecimal
someNumber = 0xAF309/256 //which is af3.09
someNumber = someNumber.toFixedNumber(1, 16);
someNumber.toString(16) === "af3.1";
Tuttavia , tenere presente che l'inquinamento del prototipo è considerato negativo quando si scrive un modulo, poiché i moduli non dovrebbero avere effetti collaterali. Quindi, per un modulo, utilizzare la prima funzione .
type Number
. Il fatto è che +(anyValue)
restituisce sempre un numero, ad es. +("45")
ritorna 45
, +(new Number(42))
ritorna 42
. È un po 'come scrivere forte la funzione. Se ne
someNumber = Math.round( 42.008 * 1e2 ) / 1e2;
non 42.01
lo è, lo è ~42.0099999999999980
. Motivo: il numero 42.01
non esiste e viene arrotondato al numero esistente più vicino. tra l'altro, prova i numeri toPrecision(18)
per stamparlo con tutte le cifre rilevanti.
Ho risolto questo problema modificandolo:
someNumber = someNumber.toFixed(2)
...a questa:
someNumber = +someNumber.toFixed(2);
Tuttavia, questo convertirà il numero in una stringa e lo analizzerà di nuovo, il che avrà un impatto significativo sulle prestazioni. Se ti interessano le prestazioni o la sicurezza dei tipi, controlla anche le altre risposte.
someNumber = Math.round(someNumber * 1e2) / 1e2
! Vedi la mia risposta per un modo più generalizzato.
Perché non usare parseFloat
?
var someNumber = 123.456;
someNumber = parseFloat(someNumber.toFixed(2));
alert(typeof(someNumber));
//alerts number
Ovviamente restituisce una stringa. Se si desidera arrotondare la variabile numerica, utilizzare invece Math.round (). Il punto di Fisso è formattare il numero con un numero fisso di posizioni decimali da visualizzare all'utente .
Cosa ti aspetteresti che ritorni quando dovrebbe formattare un numero? Se hai un numero, non puoi praticamente farci nulla, ad es 2 == 2.0 == 2.00
. Ecc., Quindi deve essere una stringa.
Per fornire un esempio del motivo per cui deve essere una stringa:
Se formatti 1.toFixed (2) otterrai '1.00'.
Questo non è uguale a 1, in quanto 1 non ha 2 decimali.
So che JavaScript non è esattamente un linguaggio delle prestazioni , ma è probabile che otterrai prestazioni migliori per un arrotondamento se usi qualcosa come: arrotondatoValore = Math.round (valore * 100) * 0,01
Perché il suo uso principale è la visualizzazione di numeri? Se si desidera arrotondare i numeri, utilizzare Math.round()
con fattori appropriati.
'42'
è un numero ... che non lo è. Solo perché una stringa contiene solo cifre non la rende un numero. Questo non è PHP. :-P
Ecco una versione leggermente più funzionale della risposta m93a
fornita.
const toFixedNumber = (toFixTo = 2, base = 10) => num => {
const pow = Math.pow(base, toFixTo)
return +(Math.round(num * pow) / pow)
}
const oneNumber = 10.12323223
const result1 = toFixedNumber(2)(oneNumber) // 10.12
const result2 = toFixedNumber(3)(oneNumber) // 10.123
// or using pipeline-operator
const result3 = oneNumber |> toFixedNumber(2) // 10.12