2011-01-12 13 views
5

Estoy mirando el siguiente SHA256 pseudocode en la wikipedia.¿Cuáles son los primeros 32 bits de la parte fraccionaria de este flotador?

Específicamente, estoy mirando la siguiente sección.

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

Estoy tratando de averiguar cómo se generó h0. Sé por el comentario que esta debería ser la parte fraccionaria de la raíz cuadrada de 2. Creo que puedo obtener la parte fraccional de la raíz cuadrada de 2 escribiendo lo siguiente. Todo el siguiente código es de python repl.

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

En la parte superior del archivo indica que la declaración de todas las constantes es Big Endian. Sé que mi entorno es Small Endian porque escribo.

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

Así, de acuerdo a mi manipulación manual del valor hexadecimal en H0, la representación de Little Endian debe ser 0x67e6096a.

>>> int(0x67e6096a) 
1743128938 

y estoy atascado. He intentado varias manipulaciones, pero ninguna de ellas termina con este resultado. No sé cómo obtener los primeros 32 bits de la parte fraccionaria de un número de punto flotante. Sé que de alguna manera mi resultado 0.41421356237309515 (flotante) se puede transformar en 1743128938 (int), pero realmente no tengo idea de cómo. ¿Cuáles son los pasos necesarios para obtener los primeros 32 bits de la parte fraccionaria de un número de coma flotante? Python solo responde por favor.

Gracias.

Respuesta

8

Endianness no importa para las constantes hexadecimales; cada dígito es un mordisco, con el mordisco menos significativo al último. Importa si manejas diferentes punteros de tamaño. Si necesita usar órdenes de byte, el módulo struct puede ayudar. De todos modos, has recuperado la parte fraccional muy bien; convirtiéndola en hexadecimal se realiza fácilmente mediante simple multiplicación y truncando, por lo que tenemos un número entero:

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

Entonces, dado que Python trata con las constantes hexadecimales como una "secuencia de nibbles" en lugar de cortas, int, largas (o lo que sea), ¿no tengo que preocuparme por el orden de los bytes? ¿Eso no haría que Python literalmente las constantes hexagonales efectivamente siempre sean Big Endian?Disculpe si es una pregunta estúpida, pero me confundo fácilmente. :) –

+0

Tipo de sí, pero esto no es nada específico de Python. Ese es simplemente el orden en que escribimos los números. Tenga en cuenta que este orden se hereda de la escritura árabe, donde el texto va de derecha a izquierda; con esa vista, es pequeño endian. Sin embargo, no está dividido en bytes, por lo que el intercambio de bytes no es relevante. –

6
  1. Usa tu calculadora en Windows para calcular la raíz cuadrada (2) (1,4142135623730950488016887242097)
  2. tomar la parte decimal (0.4142135623730950488016887242097)
  3. Multiplicar por 2^32 (1779033703,9520993849027770600526)
  4. expreso toda la parte en hexadecimal (6A09E667)

Voila. (Disculpas a OP por no hacer una respuesta de Python, pero espero que el método sea claro.)

+0

Ok, no es una pitón respuesta, pero me ilustró mi problema. Veo que el error que estaba cometiendo era intentar multiplicar la parte fraccional por 10^n, donde n es un número entero que es el más grande n en el que fractional_part_of (sqrt (2)) * (10^n) aún puede estar contenido en una entero de 4 bytes sin signo. Entonces estaba tomando ese resultado y lanzando (con piso) para obtener un número entero. Jaja, soy tan tonto. –

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

Slice, según sea necesario, por ejemplo:

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

Interesante, no tenía idea de que pudieras usar hexadecimal para representar un número de coma flotante. Aprendiendo mucho hoy –

+0

También notamos aquí que es un valor truncado en lugar de un valor redondeado. Agregar '2 ** - 33' lo redondearía a 0x6a09e668. –

Cuestiones relacionadas