2011-12-29 11 views
47

Estoy transfiriendo datos brutos como [{id: 12000000000002539, Name: "Some Name"}] y estoy obteniendo el objeto [{id: 12000000000002540, Name: "Some Name"}] después del análisis, por ahora el lado del servidor convirtiendo el ID en cadena parece ayudar. ¿Pero existe una mejor manera de transferir correctamente los datos de Bigint?transferencia JSON de bigint: 12000000000002539 se convierte a 12000000000002540?

+1

No puede hacer algo así como 'long long' en C si eso es lo que está preguntando. Cadena es probablemente la mejor manera de ir. – Chad

+5

Esto es esencialmente lo mismo que esta pregunta de ayer: http://stackoverflow.com/q/8641668/615754. JavaScript puede representar números grandes, pero con solo unos 15 o 16 dígitos de precisión. – nnnnnn

+0

No es JSON FCOL –

Respuesta

84

El valor es en realidad no exceda el valor numérico máximo en JavaScript (que es "sólo" 1,7 o algo así).

Sin embargo, el valor es que supera el rango de "precisión integral". No es que el número incorrecto se envía: más bien, es que el literal sólo puede ser representado con tanta precisión como 12000000000002540, y por lo tanto no fue nunca se el valor numérico correcto en JavaScript. (El range of integrals es de aproximadamente +/- 2 .)

Este es un fenómeno interesante de la utilización de a double relative-precision (binary64 en IEEE-754 Hablar) escriba para almacenar todos los valores numéricos, incluyendo los números enteros:

12000000000002539 === 12000000000002540 // true 

El número máximo significativo de dígitos decimales que se almacenan con precisión como un valor numérico es 15 (15,95, realmente). En lo anterior, hay 17 dígitos significativos, por lo que algunos de la información menos significativa se pierde silenciosamente. En este caso, como el analizador/motor de JavaScript lee en el valor literal.

La única manera segura de manejar números enteros de esta magnitud en JavaScript es utilizar un literal de cadena o dividirlo de otra manera (por ejemplo, un tipo numérico personalizado o un "bigint library"). Sin embargo, recomiendo simplemente usar una cadena, ya que es legible por humanos, relativamente compacto (solo dos caracteres adicionales en JSON), y no requiere serialización especial. Dado que el valor es solo un "id" en este caso, espero que las matemáticas no necesiten ser ejecutadas :)

Happy coding.

+2

¡cosas increíbles! – VvDPzZ

+7

+1 hermosa respuesta. – alex

+9

Vale la pena señalar que JSON ([RFC 4627] (http://www.ietf.org/rfc/rfc4627)) no garantiza el rango de números que los consumidores de JSON deben poder representar para que la respuesta sea diferente para otros clientes: "Una implementación puede establecer límites en el rango de números". –