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
fractionDigitsdígitos después del punto decimal. SifractionDigitsno está definido, se asume0. Específicamente, realice los siguientes pasos:
- Deje
fserToInteger(fractionDigits). (SifractionDigitsno está definido, este paso produce el valor0).- Si
f < 0of > 20, lanza una excepciónRangeError.- Deje
xeste valor numérico.- Si
xesNaN, 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
nun entero cuyo valor matemático exacto den ÷ 10^f – xsea lo más cercano posible a cero. Si hay dos de talesn, elija elnmás grande.- Si
n = 0, seamla cadena"0". De lo contrario, seamla 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
ksea la cantidad de caracteres enm.- Si
k > f, vaya al paso 18.- Deje
zser la cadena que consta def+1–kocurrencias del carácter''0''.- Deje
mser la concatenación de cadenaszym.- Deje
k = f + 1.- Sean
alos primeros caracteresk–fdem, y seanblos caracteresfrestantes dem.- Deje
mser la concatenación de las tres cuerdasa,"."yb.- Devuelve la concatenación de las cuerdas
sm.La propiedad de
lengthdel métodotoFixedes1.Si se
toFixedmétodotoFixedcon 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
toFixedpara valores defractionDigitsmenores que0o mayores que20. En este caso,toFixedno arrojaría necesariamenteRangeErrorpara dichos valores.NOTA La salida de
toFixedpuede ser más precisa quetoStringpara algunos valores porquetoStringsolo 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!