tolocalestring sirve que para number float javascript internet-explorer floating-point

sirve - tolocalestring() javascript number



Number.prototype.toFixed: increĆ­blemente correcto en Internet Explorer (3)

Considera lo siguiente:

var x = 2.175; console.log(x.toFixed(2)); // 2.17

¿Qué? No, no es sorpresa aquí. Eso es bastante obvio, ver: el literal número 2.175 realidad está almacenado en la memoria (según las reglas IEEE-754) como un valor que es solo un poco más pequeño que 2.175. Y eso es fácil de probar:

console.log(x.toFixed(20)); // 2.17499999999999982236

Así es como funciona en las últimas versiones de Firefox, Chrome y Opera en la configuración de Windows de 32 bits. Pero esa no es la pregunta.

La verdadera pregunta es cómo Internet Explorer 6 (!) Realmente logra hacerlo derecho como lo hacen los humanos:

var x = 2.175; console.log(x.toFixed(2)); // 2.18 console.log(x.toFixed(20)); // 2.17500000000000000000

De acuerdo, sobredramaticé: en realidad todos los Explorers de Internet en los que probé esto (IE8-11, ¡e incluso MS Edge!) Se comportan de la misma manera. Aún así, ¿WAT?

ACTUALIZACIÓN: Se vuelve extraño:

x=1.0;while((x-=0.1) > 0) console.log(x.toFixed(20)); IE Chrome 0.90000000000000000000 0.90000000000000002220 0.80000000000000000000 0.80000000000000004441 0.70000000000000010000 0.70000000000000006661 0.60000000000000010000 0.60000000000000008882 0.50000000000000010000 0.50000000000000011102 0.40000000000000013000 0.40000000000000013323 0.30000000000000015000 0.30000000000000015543 0.20000000000000015000 0.20000000000000014988 0.10000000000000014000 0.10000000000000014433 0.00000000000000013878 0.00000000000000013878

¿Por qué la diferencia, en todas menos en la última? ¿Y por qué no hay diferencia en el último? Es muy similar para x=0.1; while(x-=0.01)... x=0.1; while(x-=0.01)... , por cierto: hasta que nos toFixed a cero, toFixed in IE aparentemente intenta cortar algunas esquinas.

Descargo de responsabilidad: sí sé que las matemáticas de coma flotante son un poco defectuosas. Lo que no entiendo es cuál es la diferencia entre IE y el resto del mundo del navegador.


Agradezco la contribución de Eric, pero, con el debido respeto, no responde la pregunta. Admito que era demasiado irónico con esas frases "correctas" y "increíblemente correctas"; pero sí, entiendo que el comportamiento de IE es una desviación en realidad.

De todas formas. Todavía estaba buscando una explicación de por qué el IE se comporta de manera diferente, y finalmente obtuve algo que parecía una pista ... irónicamente, en el rastreador de Mozilla, en esta larga discusión . Citar:

OUTPUT IN MOZILLA: a = 0.827 ==> a.toFixed(17) = 0.82699999999999996 b = 1.827 ==> b.toFixed(17) = 1.82699999999999996 OUTPUT IN IE6: a = 0.827 ==> a.toFixed(17) = 0.82700000000000000 b = 1.827 ==> b.toFixed(17) = 1.82700000000000000

La diferencia observada en IE y Mozilla es la siguiente. IE está almacenando ''a'' como una cadena y Mozilla está almacenando ''a'' como un valor. La especificación no establece el formato de almacenamiento. Por lo tanto, cuando IE hace a.toFixed , comienza con una representación de cadena exacta, mientras que Mozilla sufre las conversiones de ida y vuelta.

Sería genial tener una especie de confirmación oficial al respecto, pero al menos eso explica todo lo que he visto hasta ahora. En particular,

console.log( 0.3.toFixed(20) ); // 0.30000000000000000000 console.log( 0.2.toFixed(20) ); // 0.20000000000000000000 console.log( (0.3 - 0.2).toFixed(20) ); // "0.09999999999999998000"


El comportamiento informado se desvía de los requisitos de la especificación ECMA .

Según la cláusula 8.5, el tipo Number tiene los valores binarios IEEE-754 de 64 bits, excepto que solo hay un NaN. Entonces 2.175 no puede ser representado exactamente; lo más cercano que puede obtener es 2.17499999999999982236431605997495353221893310546875.

Según 15.7.4.5, toFixed(20) utiliza un algoritmo que se reduce a:

  • "Sea n un entero cuyo valor matemático exacto de n ÷ 10 f - x es lo más cercano posible a cero. Si hay dos de tales n , elija el n más grande ".
  • En lo anterior, f es 20 (el número de dígitos solicitados), y x es el operando, que debe ser 2.17499999999999982236431605997495353221893310546875.
  • Esto da como resultado la selección de 217499999999999982236 para n .
  • Luego se formatea n , produciendo "2.17499999999999982236".

En primer lugar, los puntos flotantes no se pueden representar "con precisión " en números binarios. Habrá una elevación / depresión, o el valor será un poco más alto o un poco más bajo . Cuánto está elevado / deprimido depende de cómo se realice la conversión. No hay exactamente un " valor correcto " incluso para una salida de cadena de ECMAScript a toFixed() .

Pero los estándares de ECMA hacen las cosas más interesantes al establecer estándares. Lo cual es algo bueno en mi opinión. Es como " Si todos vamos a cometer errores de todos modos, hagamos el mismo " .

Entonces, la pregunta ahora sería cómo y por qué IE se desvía de los Estándares. Examinemos los siguientes casos de prueba.

Los candidatos son IE 10.0.9200.16688 y Chrome 30.0.1599.69, que se ejecutan en x64 Windows 8 Pro.

Case Code IE (10) Chrome (30) -------------------------------------------------------------------------------- A (0.06).toFixed(20) 0.60000000000000000000 0.05999999999999999778 B (0.05+0.01).toFixed(20) 0.06000000000000000500 0.06000000000000000472

Entonces, independientemente de que sea IE o Chrome, vemos que (0.06) no es exactamente igual a (0.05+0.01) . ¿Porqué es eso? Es porque (0.06) tiene una representación muy cercana pero no igual a (0.06), también lo hace (0.05) y (0.01). Cuando realizamos una operación, como una adición, los errores muy menos significativos pueden resumirse para convertirse en un error de magnitud ligeramente diferente .

Ahora, la diferencia en el valor representado en diferentes navegadores se puede ver afectada por dos motivos:

  • El algoritmo de conversión utilizado.
  • Cuando la conversión se lleva a cabo.

Ahora no sabemos qué usa algo IE ya que no puedo ver su origen. Pero los casos de prueba anteriores demuestran claramente otra cosa, IE y Chrome manejan la conversión " no solo de manera diferente " sino también " en una ocasión diferente ".

En JavaScript, cuando creamos un número (instancia aka de una clase Number con o sin la new palabra clave), en realidad proporcionamos un literal . El literal siempre es una cadena incluso si denota un número [1] . El navegador analiza el literal y crea el objeto y asigna el valor representado.

Ahora, aquí es donde las cosas tienden a ir de diferentes maneras. IE mantiene la conversión hasta que se necesite. Eso significa que hasta que se lleve a cabo una operación, IE mantiene el número como literal (o como un formato intermedio). Pero Chrome lo convierte de inmediato en el formato operativo.

Una vez finalizada la operación, IE no vuelve al formato literal o al formato intermedio, ya que no tiene sentido y puede causar una ligera pérdida de precisión.

Espero que eso aclare algo.

[1] El valor representado en el código siempre es literal s. Si los cita, se llaman String Literal s.