15

I am looking at the following SHA256 pseudocode on wikipedia.

Specifically, I am looking at the following section.

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

I am trying to figure out how h0 was generated. I know from the comment that this should be the fractional part of the square root of 2. I believe I can get the fractional part of the square root of 2 by typing the following. All the following code is from the python repl.

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

At the top of the file it states that the declaration of all constants are Big Endian. I know that my environment is Small Endian because I type.

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

So, according to my manual manipulation of the hex value in h0, the Little Endian representation should be 0x67e6096a.

>>> int(0x67e6096a)
1743128938

And I am stuck. I have tried various manipulations, but non of them end up with this result. I do not know how to get the first 32 bits of the fractional part of a floating point number. I know that somehow my 0.41421356237309515 (float) result can be transformed into 1743128938 (int), but I really have no idea how. What are the steps necessary to get the first 32 bits of the fractional part of a floating point number? Python answers only please.

Thank you.

Community
  • 1
  • 1
Stephen Cagle
  • 14,124
  • 16
  • 55
  • 86

3 Answers3

18
  1. Use your calculator on Windows to calculate sqrt(2) (1.4142135623730950488016887242097)
  2. Take the decimal part (0.4142135623730950488016887242097)
  3. Multiply by 2^32 (1779033703.9520993849027770600526)
  4. Express the whole part in hex (6A09E667)

Voila. (Apologies to OP for not doing a Python answer but I hope the method is clear.)

John
  • 15,990
  • 10
  • 70
  • 110
  • 2
    Ok, it isn't a python answer, but it did illustrate my problem to me. I see that the mistake I was making was attempting to multiply the fractional part by 10^n, where n is a integer that is the largest n wherein fractional_part_of(sqrt(2))*(10^n) can still be contained in a unsigned 4 byte integer. I was then taking that result and casting (with flooring) to get a integer. Haha, I am so silly. – Stephen Cagle Jan 13 '11 at 00:06
13

Endianness does not matter for hexadecimal constants; each digit is a nibble, with the least significant nibble last. It does matter if you deal with differing size pointers. If you do need to use byte orders, the struct module can help. Anyhow, you've retrieved the fractional part just fine; converting it to hex is easily done by simply multiplying and truncating, so we get an integer:

>>> hex(int(math.modf(math.sqrt(2))[0]*(1<<32)))
'0x6a09e667'
Yann Vernier
  • 15,414
  • 2
  • 28
  • 26
  • So, because Python deals with hex constants as a "stream of nibbles" rather than as a short, int, long (or whatever), I don't have to worry about byte order? Would that not make Python literal hex constants effectively always Big Endian? Apologies if a stupid question, but I am easily confused. :) – Stephen Cagle Jan 12 '11 at 23:59
  • Sort of yes, but this is nothing Python specific. That is simply the order we write numbers. Note that this order is inherited from arabic writing, where text goes right to left; with that view, it's little endian. It's not divided into bytes, however, so byte swapping is not relevant. – Yann Vernier Jan 13 '11 at 00:25
6

Python can display the exact IEEE 754 floating point data as a hexadecimal value. It includes the implied leading 1, the mantissa in hex and the exponent value:

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

Slice as needed, for example:

>>> '0x'+math.sqrt(2).hex().split('.')[1][:8]
'0x6a09e667'
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251