¿Me estoy perdiendo de algo?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
¿ Por qué.toFixed()
devuelve una cadena?
Quiero redondear el número a 2 dígitos decimales.
¿Me estoy perdiendo de algo?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
¿ Por qué.toFixed()
devuelve una cadena?
Quiero redondear el número a 2 dígitos decimales.
Respuestas:
Devuelve una cadena porque 0.1, y sus potencias (que se usan para mostrar fracciones decimales), no son representables (al menos no con total precisión) en sistemas binarios de punto flotante.
Por ejemplo, 0.1 es realmente 0.1000000000000000055511151231257827021181583404541015625, y 0.01 es realmente 0.01000000000000000020816681711721685132943093776702880859375. (Gracias a BigDecimal
por demostrar mi punto. :-P)
Por lo tanto (en ausencia de coma flotante decimal o tipo de número racional), su salida como una cadena es la única forma de recortarlo exactamente con la precisión requerida para la visualización.
toFixed
es una función de formateo, que tiene el único propósito de convertir un número en una cadena, formateándola usando el número especificado de decimales. La razón por la que devuelve una cadena es porque se supone que devuelve una cadena, y si se nombrara toStringFixed
en su lugar, OP no se sorprendería de los resultados. El único problema aquí es que OP esperaba que funcionara Math.round
sin consultar la referencia de JS.
Number.prototype.toFixed
es una función diseñada para formatear un número antes de imprimirlo. Es de la familia de toString
, toExponential
y toPrecision
.
Para redondear un número, haría esto:
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;
}
.
O si desea una función " nativa ", puede extender el 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";
Sin embargo , tenga en cuenta que contaminar el prototipo se considera malo cuando está escribiendo un módulo, ya que los módulos no deberían tener ningún efecto secundario. Entonces, para un módulo, use la primera función .
type Number
. La cosa es que +(anyValue)
siempre devuelve un número, por ejemplo. +("45")
vuelve 45
, +(new Number(42))
vuelve 42
. Es como escribir una función fuerte. Si tiene el hábito, puede evitar muchos errores :)
someNumber = Math.round( 42.008 * 1e2 ) / 1e2;
no es 42.01
, es ~42.0099999999999980
. Motivo: El número 42.01
no existe y se redondea al número existente más cercano. por cierto, prueba los números toPrecision(18)
para imprimirlo con todos los dígitos relevantes.
He resuelto este problema cambiando esto:
someNumber = someNumber.toFixed(2)
...a esto:
someNumber = +someNumber.toFixed(2);
Sin embargo, esto convertirá el número en una cadena y lo analizará nuevamente, lo que tendrá un impacto significativo en el rendimiento. Si le preocupa el rendimiento o la seguridad de los tipos, verifique también las otras respuestas.
someNumber = Math.round(someNumber * 1e2) / 1e2
! Vea mi respuesta para una forma más generalizada.
¿Por qué no usar parseFloat
?
var someNumber = 123.456;
someNumber = parseFloat(someNumber.toFixed(2));
alert(typeof(someNumber));
//alerts number
Por supuesto que devuelve una cadena. Si quisiera redondear la variable numérica, usaría Math.round () en su lugar. El objetivo de toFixed es formatear el número con un número fijo de decimales para mostrar al usuario .
¿Qué esperarías que devuelva cuando se supone que formatea un número? Si tiene un número, no puede hacer nada con él, por ejemplo, 2 == 2.0 == 2.00
etc., por lo que tiene que ser una cadena.
Para proporcionar un ejemplo de por qué tiene que ser una cadena:
Si formatea 1.toFixed (2) obtendría '1.00'.
Esto no es lo mismo que 1, ya que 1 no tiene 2 decimales.
Sé que JavaScript no es exactamente un lenguaje de rendimiento , pero es probable que obtenga un mejor rendimiento para un redondeo si usa algo como: roundedValue = Math.round (valor * 100) * 0.01
¿Porque su uso principal es mostrar números? Si desea redondear números, Math.round()
úselo con los factores apropiados.
'42'
es un número ... que no lo es. El hecho de que una cadena contenga solo dígitos no lo convierte en un número. Esto no es PHP. :-P
Aquí hay una versión un poco más funcional de la respuesta m93a
proporcionada.
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