Question

Certaines de mes données sont des entiers 64 bits. Je souhaite les envoyer à un programme JavaScript exécuté sur une page.

Toutefois, autant que je sache, les nombres entiers dans la plupart des implémentations JavaScript sont des quantités signées 32 bits.

Mes deux options semblent être:

  1. Envoyez les valeurs sous forme de chaînes
  2. Envoyez les valeurs sous forme de nombres à virgule flottante 64 bits

L'option (1) n'est pas parfaite, mais l'option (2) semble beaucoup moins parfaite (perte de données).

Comment avez-vous géré cette situation?

Était-ce utile?

La solution

Cela semble être moins un problème avec JSON que un problème avec Javascript lui-même. Que comptez-vous faire avec ces chiffres? S'il ne s'agit que d'un jeton magique que vous devez renvoyer ultérieurement sur le site Web, utilisez simplement une chaîne contenant la valeur. Si vous devez réellement utiliser l'arithmétique sur la valeur, vous pouvez éventuellement écrire vos propres routines Javascript pour l'arithmétique 64 bits.

Une façon de représenter les valeurs en Javascript (et donc en JSON) consiste à scinder les nombres en deux valeurs 32 bits, par exemple.

  [ 12345678, 12345678 ]

Pour fractionner une valeur 64 bits en deux valeurs 32 bits, procédez comme suit:

  output_values[0] = (input_value >> 32) & 0xffffffff;
  output_values[1] = input_value & 0xffffffff;

Ensuite, pour recombiner deux valeurs 32 bits en une valeur 64 bits:

  input_value = ((int64_t) output_values[0]) << 32) | output_values[1];

Autres conseils

Il existe en fait une limitation au niveau de précision JavaScript / ECMAScript à 53 bits pour les entiers (ils sont stockés dans la mantisse d'un tampon de mémoire & double-like & "8 octets"). Par conséquent, la transmission de gros nombres au format JSON ne sera pas désérialisée comme prévu par le client JavaScript, ce qui les tronquerait à sa résolution 53 bits.

> parseInt("10765432100123456789")
10765432100123458000

Voir le Number.MAX_SAFE_INTEGER constant . et Number.isSafeInteger() fonction:

  

La constante MAX_SAFE_INTEGER a une valeur de 9007199254740991. le   le raisonnement derrière ce nombre est que JavaScript utilise la double précision   les numéros de format à virgule flottante spécifiés dans IEEE 754 et ne peuvent   représente en toute sécurité des nombres entre -(2^53 - 1) et 2^53 - 1.

     

Coffre-fort dans ce contexte fait référence à la possibilité de représenter des entiers   exactement et de les comparer correctement. Par exemple,   Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 sera   évaluer à true, ce qui est mathématiquement incorrect. Voir   Edm.Int64 pour plus d'informations.

En raison de la résolution des flottants en JavaScript, utilisez & "; nombres à virgule flottante 64 bits &"; comme vous l'avez proposé souffrirait de la même restriction.

IMHO, la meilleure option est de transmettre des valeurs telles que du texte. Il s’agirait toujours d’un contenu JSON parfaitement lisible et d’un travail facile au niveau JavaScript.

Une " chaîne pure " La représentation est ce que OData spécifie, pour ses Edm.Decimal ou ".._str": types .

Dans ce cas, l'API Twitter ajoute un champ <=> spécifique dans le code JSON, en tant que tel:

{
   "id": 10765432100123456789,           // for JSON compliant clients
   "id_str": "10765432100123456789",     // for JavaScript
    ...
}

J'aime beaucoup cette option, car elle serait toujours compatible avec les clients compatibles int64. En pratique, un tel contenu dupliqué dans le JSON ne fera pas beaucoup de mal s'il est dégonflé / gzippé au niveau HTTP.

Une fois transmise sous forme de chaîne, vous pouvez utiliser des bibliothèques telles que strint & # 8211; une bibliothèque JavaScript pour les entiers codés par chaîne permettant de gérer ces valeurs.

Le type de numéro de Javascript (64 bits IEEE 754) n'a qu'une précision d'environ 53 bits.

Toutefois, si vous n'avez pas besoin d'ajouter ni de multiplier, vous pouvez conserver la valeur 64 bits sous forme de chaînes de 4 caractères, car JavaScript utilise le format UTF-16.

Par exemple, 1 pourrait être codé comme & "; \ u0000 \ u0000 \ u0000 \ u0001 &"; Cela présente l’avantage que la comparaison de valeur (==, & Gt ;, & Lt;) fonctionne comme prévu sur les chaînes. Il semble également simple d'écrire des opérations sur les bits:

function and64(a,b) {
    var r = "";
    for (var i = 0; i < 4; i++)
        r += String.fromCharCode(a.charCodeAt(i) & b.charCodeAt(i));
    return r;
}

La représentation du nombre JS est un ieee double standard, vous ne pouvez donc pas représenter un entier 64 bits. vous obtenez peut-être 48 bits de précision int réelle dans un double, mais tous les bitops JS réduisent à une précision de 32 bits (c'est ce que la spécification requiert. yay!) donc si vous avez vraiment besoin d'un int de 64 bits en js, vous devrez implémenter votre propre Bibliothèque logique int 64 bits.

JSON lui-même ne se soucie pas des limites d'implémentation. Votre problème est que JS ne peut pas gérer vos données, pas le protocole. En d’autres termes, votre code client JS doit utiliser l’une de ces options non parfaites.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top