places - truncate number javascript
Math.round(num) vs num.toFixed(0) e incoherencias del navegador (6)
Creo que FF está haciendo lo correcto con to Fixed, ya que el paso 10 a continuación dice "Si hay dos de esos n, elija el n más grande".
Y como dijo Grant Wagner : Use Math.ceil (x) o Math.floor (x) en lugar de x.toFixed () .
Todo a continuación es de la especificación del lenguaje ECMAScript :
15.7.4.5
Number.prototype.toFixed (fractionDigits)
Devuelve una cadena que contiene el número representado en notación de punto fijo con dígitos de
fractionDigits
dígitos después del punto decimal. SifractionDigits
no está definido, se asume0
. Específicamente, realice los siguientes pasos:
- Deje
f
serToInteger(fractionDigits)
. (SifractionDigits
no está definido, este paso produce el valor0
).- Si
f < 0
of > 20
, lanza una excepciónRangeError
.- Deje
x
este valor numérico.- Si
x
esNaN
, devuelve la cadena"NaN"
.- Seamos la cadena vacía.
- Si
x ≥ 0
, vaya al paso 9.- Seamos
"-"
.- Deje
x = –x
.- Si
x ≥ 10^21
, dejem = ToString(x)
y vaya al paso 20.- Sea
n
un entero cuyo valor matemático exacto den ÷ 10^f – x
sea lo más cercano posible a cero. Si hay dos de talesn
, elija eln
más grande.- Si
n = 0
, seam
la cadena"0"
. De lo contrario, seam
la cadena que consiste en los dígitos de la representación decimal den
(en orden, sin ceros a la izquierda).- Si
f = 0
, vaya al paso 20.- Deje
k
sea la cantidad de caracteres enm
.- Si
k > f
, vaya al paso 18.- Deje
z
ser la cadena que consta def+1–k
ocurrencias del carácter''0''
.- Deje
m
ser la concatenación de cadenasz
ym
.- Deje
k = f + 1
.- Sean
a
los primeros caracteresk–f
dem
, y seanb
los caracteresf
restantes dem
.- Deje
m
ser la concatenación de las tres cuerdasa
,"."
yb
.- Devuelve la concatenación de las cuerdas
s
m
.La propiedad de
length
del métodotoFixed
es1
.Si se
toFixed
métodotoFixed
con más de un argumento, entonces el comportamiento no está definido (ver sección 15).Se permite que una implementación amplíe el comportamiento de a
toFixed
para valores defractionDigits
menores que0
o mayores que20
. En este caso,toFixed
no arrojaría necesariamenteRangeError
para dichos valores.NOTA La salida de
toFixed
puede ser más precisa quetoString
para algunos valores porquetoString
solo imprime suficientes dígitos significativos para distinguir el número de los valores numéricos adyacentes. Por ejemplo,(1000000000000000128).toString()
devuelve"1000000000000000100"
, mientras que(1000000000000000128).toFixed(0)
devuelve"1000000000000000128"
.
Considera el siguiente código:
for (var i=0;i<3;i++){
var num = i + 0.50;
var output = num + " " + Math.round(num) + " " + num.toFixed(0);
alert(output);
}
En Opera 9.63 obtengo:
0.5 1 0
1.5 2 2
2.5 3 2
En FF 3.03 obtengo:
0.5 1 1
1.5 2 2
2.5 3 3
En IE 7 consigo:
0.5 1 0
1.5 2 2
2.5 3 3
Tenga en cuenta los resultados en negrita. ¿Por qué están presentes estas inconsistencias? ¿Esto significa que se debe evitar toFixed(0)
? ¿Cuál es la forma correcta de redondear un número al número entero más cercano?
Definitivamente parece de esa manera, si recibes respuestas inconsistentes.
Solo puedo adivinar que su intención al usarFixed (0) es convertir un número decimal en un entero, en cuyo punto recomiendo Math.floor (). Hay un poco más de discusión sobre la mejor manera de hacerlo en esta pregunta .
Editar: para responder a su edición, use Math.round
. También podría prototipar el objeto Number
para que haga su oferta si prefiere esa sintaxis.
Number.prototype.round = function() {
return Math.round(this);
}
var num = 3.5;
alert(num.round())
Nunca utilicé Number.toFixed()
antes (sobre todo porque la mayoría de las bibliotecas JS proporcionan un método toInt()
), pero a juzgar por sus resultados, diría que sería más consistente usar los métodos Math
( round
, floor
, ceil
) a continuación, a la toFixed
-browser si está buscando.
En lugar de toFixed(0)
use Math.ceil()
o Math.floor()
, dependiendo de lo que se requiera.
Para abordar sus dos cuestiones / preguntas originales :
Math.round (num) vs num.toFixed (0)
El problema aquí radica en la idea errónea de que siempre deberían dar el mismo resultado. De hecho, se rigen por reglas diferentes. Mire los números negativos, por ejemplo. Debido a que Math.round
usa "round half up" como regla, verá que Math.round(-1.5)
evalúa a -1
aunque Math.round(1.5)
evalúe a 2
.
Number.prototype.toFixed
, por otro lado, usa lo que es básicamente equivalente a "round half away from zero" como regla, de acuerdo con el paso 6 de la especificación , que esencialmente dice que se deben tratar los negativos como números positivos, y luego volver a agregar el signo negativo al final. Por lo tanto, (-1.5).toFixed(0) === "-2"
y (1.5).toFixed(0) === "2"
son declaraciones verdaderas en todos los navegadores que cumplen con las especificaciones. Tenga en cuenta que estos valores son cadenas, no números. Observe además que tanto -1.5.toFixed(0)
como -(1.5).toFixed(0)
son === -2
(el número) debido a la precedencia del operador.
Inconsistencias del navegador
La mayoría de los navegadores modernos, o al menos los que se espera que admita en el momento de escribir este documento, excepto IE, deben implementar las especificaciones correctamente. (Según el comentario de Renee , se ha toFixed
problema toFixed
que señaló en Opera, presumiblemente desde que comenzaron a usar el mismo motor JS que Chrome.) Todavía vale la pena reiterar que, incluso si las especificaciones se implementaron de manera consistente en todos los navegadores, el comportamiento definido en la especificación, particularmente para el redondeo toFixed
, puede ser poco intuitivo para desarrolladores de JS "meramente mortales" que esperan exactitud matemática verdadera -ver Javascript a fijo no redondeado y este error "funciona como estaba previsto" que se presentó en el motor V8 JS por ejemplo.
Conclusión
En resumen, estas son dos funciones diferentes con dos tipos de devolución diferentes y dos conjuntos de reglas diferentes para el redondeo.
Como otros han sugerido, también me gustaría decir "use cualquier función que se adapte a su caso de uso particular" (teniendo especial cuidado de observar las peculiaridades de toFixed
, especialmente la implementación errónea de IE). Personalmente me inclinaría más a recomendar alguna combinación explícita de Editar: ... sin embargo, después de volver y leer su aclaración, su caso de uso (redondeando a un número entero) definitivamente requiere la función Math.round/ceil/floor
, una vez más, como han mencionado otros.Math.round
apropiadamente nombrada.
toFixed () devuelve un valor de cadena. De Javascript: la guía definitiva
Convierte un número en una cadena que contiene un número específico de dígitos después del lugar decimal.
Math.round () devuelve un entero.
Claramente, toFixed () parece ser más uso para el dinero, por ejemplo,
''$'' + 12.34253.toFixed (2) = ''$ 12.34''
¡Parece una gran pena que to Fix () no parezca redondear correctamente!