2011-01-12 10 views
5

Sto guardando il seguente SHA256 pseudocode su wikipedia.Quali sono i primi 32 bit della parte frazionaria di questo float?

In particolare, sto osservando la seguente sezione.

//Initialize variables 
//(first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19): 
h0 := 0x6a09e667 

Sto cercando di capire come è stato generato h0. So dal commento che questa dovrebbe essere la parte frazionaria della radice quadrata di 2. Credo di poter ottenere la parte frazionaria della radice quadrata di 2 digitando quanto segue. Tutto il codice seguente è dal python repl.

>>> math.modf(math.sqrt(2))[0] 
0.41421356237309515 

Nella parte superiore del file si afferma che la dichiarazione di tutte le costanti è Big Endian. So che il mio ambiente è Small Endian perché scrivo.

>>> import sys 
>>> sys.byteorder 
'little' 

Quindi, secondo la mia manipolazione manuale del valore esadecimale nel h0, la rappresentazione Endian Piccolo dovrebbe essere 0x67e6096a.

>>> int(0x67e6096a) 
1743128938 

E io sono bloccato. Ho provato varie manipolazioni, ma nessuna di esse finisce con questo risultato. Non so come ottenere i primi 32 bit della parte frazionaria di un numero in virgola mobile. So che in qualche modo il mio risultato 0.41421356237309515 (float) può essere trasformato in 1743128938 (int), ma non ho davvero idea di come. Quali sono i passaggi necessari per ottenere i primi 32 bit della parte frazionaria di un numero in virgola mobile? Python risponde solo per favore.

Grazie.

risposta

8

L'endianità non ha importanza per le costanti esadecimali; ogni cifra è un bocconcino, con il bocconcino meno significativo per ultimo. È importante se gestisci diversi indicatori di dimensioni. Se è necessario utilizzare gli ordini byte, il modulo struct può essere d'aiuto. Ad ogni modo, hai recuperato la parte frazionaria bene; conversione in esadecimale è fatto facilmente semplicemente moltiplicando e troncamento, in modo da ottenere un numero intero:

>>> hex(int(math.modf(math.sqrt(2))[0]*(1<<32))) 
'0x6a09e667' 
+0

Quindi, dato che Python si occupa di costanti esadecimali come "flusso di nibbles" piuttosto che come short, int, long (o quant'altro), non devo preoccuparmi dell'ordine dei byte? Non renderebbe effettivamente le costanti esagonali letterali di Python sempre Big Endian?Mi scuso se una domanda stupida, ma sono facilmente confuso. :) –

+0

Sort of yes, ma questo non è niente in Python. Questo è semplicemente l'ordine in cui scriviamo i numeri. Nota che questo ordine è ereditato dalla scrittura araba, dove il testo va da destra a sinistra; con quella vista, è little endian. Tuttavia, non è diviso in byte, quindi lo scambio di byte non è rilevante. –

6
  1. utilizzare la calcolatrice su Windows per calcolare sqrt (2) (1,4142135623730950488016887242097)
  2. Prendere la parte decimale (0,4142135623730950488016887242097)
  3. Moltiplicare per 2^32 (1779033703,9520993849027770600526)
  4. espresso tutta la parte in esadecimale (6A09E667)

Voila. (Chiede scusa per non aver risposto a Python ma spero che il metodo sia chiaro)

+0

Ok, non è un pitone risposta, ma mi ha illustrato il mio problema. Vedo che l'errore che stavo facendo stava tentando di moltiplicare la parte frazionaria di 10^n, dove n è un numero intero che è il n maggiore in cui fractional_part_of (sqrt (2)) * (10^n) può ancora essere contenuto in un intero a 4 byte senza segno. Stavo quindi prendendo quel risultato e il casting (con la pavimentazione) per ottenere un numero intero. Haha, sono così sciocco. –

3
>>> math.sqrt(2).hex() 
'0x1.6a09e667f3bcdp+0' 

Fetta come necessario, per esempio:

>>> '0x'+math.sqrt(2).hex().split('.')[1][:8] 
'0x6a09e667' 
+0

Interessante, non avevo idea di poter usare hex per rappresentare un numero in virgola mobile. Imparare molto oggi. –

+0

Abbiamo anche notato che è un valore troncato piuttosto che un valore arrotondato. Aggiungere '2 ** - 33' lo arrotonderebbe a 0x6a09e668. –

Problemi correlati