round places number node float decimals javascript cross-browser

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. Si fractionDigits no está definido, se asume 0 . Específicamente, realice los siguientes pasos:

  1. Deje f ser ToInteger(fractionDigits) . (Si fractionDigits no está definido, este paso produce el valor 0 ).
  2. Si f < 0 o f > 20 , lanza una excepción RangeError .
  3. Deje x este valor numérico.
  4. Si x es NaN , devuelve la cadena "NaN" .
  5. Seamos la cadena vacía.
  6. Si x ≥ 0 , vaya al paso 9.
  7. Seamos "-" .
  8. Deje x = –x .
  9. Si x ≥ 10^21 , deje m = ToString(x) y vaya al paso 20.
  10. Sea n un entero cuyo valor matemático exacto de n ÷ 10^f – x sea ​​lo más cercano posible a cero. Si hay dos de tales n , elija el n más grande.
  11. Si n = 0 , sea m la cadena "0" . De lo contrario, sea m la cadena que consiste en los dígitos de la representación decimal de n (en orden, sin ceros a la izquierda).
  12. Si f = 0 , vaya al paso 20.
  13. Deje k sea ​​la cantidad de caracteres en m .
  14. Si k > f , vaya al paso 18.
  15. Deje z ser la cadena que consta de f+1–k ocurrencias del carácter ''0'' .
  16. Deje m ser la concatenación de cadenas z y m .
  17. Deje k = f + 1 .
  18. Sean a los primeros caracteres k–f de m , y sean b los caracteres f restantes de m .
  19. Deje m ser la concatenación de las tres cuerdas a , "." y b .
  20. Devuelve la concatenación de las cuerdas s m .

La propiedad de length del método toFixed es 1 .

Si se toFixed método toFixed 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 de fractionDigits menores que 0 o mayores que 20 . En este caso, toFixed no arrojaría necesariamente RangeError para dichos valores.

NOTA La salida de toFixed puede ser más precisa que toString para algunos valores porque toString 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 Math.round/ceil/floor , una vez más, como han mencionado otros. 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 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!