Convertir une chaîne avec une représentation hexagonale à double d'un IEEE-754 dans la variable numérique JavaScript

StackOverflow https://stackoverflow.com/questions/1597709

Question

Supposons que j'ai un nombre hexadécimal « 4072508200000000 » et je veux le numéro de virgule flottante qu'il représente (293,03173828125000) dans le double format IEEE-754 pour être mis dans une variable JavaScript.

Je peux penser à une manière qui utilise un certain masquage et un appel à pow (), mais est-il une solution plus simple?

Une solution côté client est nécessaire.

Cela peut aider. Il est un site qui vous permet d'entrer un codage hexadécimal d'un IEEE-754 et obtenir une analyse de mantisse et exposant.

http://babbage.cs.qc.edu/IEEE-754/ 64bit.html

Parce que les gens ont toujours tendance à demander « pourquoi ?, » voici pourquoi. Je suis en train de remplir un existant, mais incomplète la mise en œuvre de Procol de Google (buffers __gVirt_NP_NN_NNPS<__ protobuf)

Était-ce utile?

La solution

Je ne sais pas d'une bonne façon. Il peut certainement être fait à la dure, voici un exemple simple précision tout à fait dans JavaScript:

js> a = 0x41973333
1100428083
js> (a & 0x7fffff | 0x800000) * 1.0 / Math.pow(2,23) * Math.pow(2,  ((a>>23 & 0xff) - 127))
18.899999618530273

Une mise en œuvre de la production devrait considérer que la plupart des champs ont des valeurs magiques, généralement mis en œuvre en spécifiant une interprétation particulière pour ce qui aurait été le plus grand ou plus petit. Ainsi, détecter NaNs et infinités. L'exemple ci-dessus doit être vérifier pour les négatifs. (A & 0x80000000)

Mise à jour: Ok, je l'ai pour deux de couple, aussi. Vous ne pouvez pas étendre directement la technique ci-dessus, car la représentation interne JS est un double, et ainsi par sa définition, il peut gérer au mieux une chaîne de bits de longueur 52, et il ne peut pas passer plus de 32 du tout.

Ok, vous permet de doubler d'abord couper une chaîne les bas 8 chiffres ou 32 bits; les traiter avec un objet séparé. Puis:

js> a = 0x40725082      
1081233538
js> (a & 0xfffff | 0x100000) * 1.0 / Math.pow(2, 52 - 32) * Math.pow(2, ((a >> 52 - 32 & 0x7ff) - 1023))
293.03173828125
js> 

J'ai gardé l'exemple ci-dessus parce qu'il est de l'OP. Un cas plus difficile est lorsque les faibles ont une valeur de 32 bits. Voici la conversion de 0x40725082deadbeef, une pleine double précision:

js> a = 0x40725082
1081233538
js> b = 0xdeadbeef
3735928559
js> e = (a >> 52 - 32 & 0x7ff) - 1023
8
js> (a & 0xfffff | 0x100000) * 1.0 / Math.pow(2,52-32) * Math.pow(2, e) +          
     b * 1.0 / Math.pow(2, 52) * Math.pow(2, e)
293.0319506442019
js> 

Il y a des sous-expressions évidentes que vous pouvez factoriser mais je l'ai laissé cette façon afin que vous puissiez voir comment il se rapporte au format.

Autres conseils

Un ajout rapide à la solution de DigitalRoss, pour ceux qui trouvent cette page via Google comme je l'ai fait.

En dehors des cas de pointe pour +/- Infinity et NaN, que j'aimerais entrée, vous devez également tenir compte du signe du résultat:

s = a >> 31 ? -1 : 1

Vous pouvez ensuite inclure s dans la multiplication finale pour obtenir le résultat correct.

Je pense que pour une solution peu endian vous aurez également besoin d'inverser les bits a et b et de les échanger.

scroll top