Non so di un buon modo. Certamente può essere fatto nel modo più difficile, ecco un esempio singola precisione totalmente all'interno di JavaScript:
js> a = 0x41973333
1100428083
js> (a & 0x7fffff | 0x800000) * 1.0/Math.pow(2,23) * Math.pow(2, ((a>>23 & 0xff) - 127))
18.899999618530273
Un'implementazione produzione dovrebbe prendere in considerazione che la maggior parte dei campi hanno valori magici, tipicamente implementato specificando un'interpretazione speciale per quello che sarebbe stato il più grande o il più piccolo. Quindi, rilevare NaN
s e infiniti. L'esempio sopra dovrebbe controllare i negativi. (a & 0x80000000)
Aggiornamento: Ok, ce l'ho anche per il doppio. Non è possibile estendere direttamente la tecnica di cui sopra perché la rappresentazione JS interna è doppia e quindi, per definizione, può gestire al meglio una stringa di lunghezza 52 e non può spostarsi di oltre 32.
Ok, per fare il doppio, prima interrompi come una stringa le 8 cifre basse o 32 bit; elaborarli con un oggetto separato. Poi:
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>
ho mantenuto l'esempio precedente perché è dal OP. Un caso più difficile è quando i 32 bit bassi hanno un valore. Qui è la conversione di 0x40725082deadbeef, una full-precisione doppia:
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>
Ci sono alcune ovvie sottoespressioni è possibile fattore di fuori, ma ho lasciato in questo modo modo da poter vedere come si riferisce al formato.
Personalmente vorrei iniziare tagliando il valore esadecimale con una regex nei pezzi separati. Poi, li valuterei come interi, e alla fine proverei a trasformarli in un float. Sembra qualcosa che sarà complicato, perché dovrai farlo in modo tale che il runtime di Javascript non perda alcun bit lungo la strada. – Pointy
Per la massima portabilità, è necessario considerare che i doppi IEEE-754 possono essere big-endian o little-endian. Se si conosce la convenzione utilizzata dall'input esadecimale, una soluzione lato client che utilizza pow() dovrebbe essere portatile. Se si decide di utilizzare una sorta di approccio di tipo puning, la piattaforma client endianness per i doppi dovrebbe essere controllata per prima. –
@Jim Lewis: Ho una bandiera che mi dice big o little endian. – Nosredna