Converting from a C double transferred in two hex strings - python

my very first day with Python.
I like to filter on a trace file generated by C.
Each double from C is formatted in the file by
two hex strings representing 32 bit of the 64 double.
e.g. 1234567890.3 (C double)
inside file:
0xb4933333
0x41d26580
How can I parse and combine it to further work with a Python float?
Thanks in advance

You can use struct, using the 'd' modifier for 'double':
>>> import struct
>>> num1 = '0xb4933333'
>>> num2 = '0x41d26580'
>>> struct.unpack('!d', (num2[2:]+num1[2:]).decode('hex'))[0]
1234567890.3
Be careful what order you append the doubles in, the above assumes a big-endian machine. Also, I stripped 0x as the decode function doesn't expect it.
edit: If you're using Python 3, you need to use bytes.fromhex instead of ''.decode('hex').
Just to give an alternative (the above is a very nice solution):
>>> import struct
>>> num1 = '0xb4933333'
>>> num2 = '0x41d26580'
>>> low_word = int(num1, 16)
>>> high_word = int(num2, 16)
>>> representation = struct.pack('>II', high_word, low_word)
>>> result = struct.unpack('>d', representation)
>>> result[0]
1234567890.3

Here is a the IEEE standard for floating points and how it is created:
http://www.psc.edu/general/software/packages/ieee/ieee.php

Related

String of bits to binary format Python

This seems really simple but I can't figure it out.
I have a string of bits in a string format and want to convert it to a binary format.
I assumed placing the string inside of the bin() function would work but it doesn't.
string = "01101"
print(bin(string))
string = "01101"
print(bin(int(string,2)))
It depends what you mean by binary format.
Here's a few examples of what you can do:
>>> int('01101', 2)
13
>>> number = 13
>>> bin(number)
'0b1101'
>>> oct(number)
'0o15'
>>> hex(number)
'0xd'
>>> f'{number:08b}'
'00001101'

How can I send a hex number and later do the necessary processing?

I am using Python 3.6.8 and the Eclipse IDE. I'm trying to rearrange the hex value. My code snippet is as follows:
def RearrangeData(Data, dataType):
Data= Data[6:] + Data[4:6] + Data[2:4] + Data[0:2]
return data
I'm calling this function as
#xxxxxxxx is a jumbled hex value and it is of type Float
RearrangeData(xxxxxxxx, Float)
In 3.6.8, the interpreter takes the input as int and not as a string. How can this be fixed? Using what attribute can I decode a hex value for example(0x3F800000) to its IEEE-754 equivalent value? In Python 2.7.5, I could use RearragedData.decode('hex'). What can I use in Python 3.6.8?
If you have a string with hexadecimal digits representing a floating point number in big-endian format, use a combination of struct and codecs to first unhexlify the hex string to binary, then unpack it into a float.
>>> import struct, codecs
>>> struct.unpack('>f', codecs.decode('3FA66666', 'hex'))
(1.2999999523162842,)
If you have an integer, 0x3FA66666 (i.e. 1067869798 in decimal), you can call hex() on it, strip the 0x prefix and do the above:
>>> v = 0x3FA66666
1067869798
>>> v_hex = hex(v)[2:]
'3fa66666'
>>> struct.unpack('>f', codecs.decode(v_hex, 'hex'))
(1.2999999523162842,)

Binary Data in Python

I have a string of binary I'm trying to convert to ints. The chunks were originally 8 hex chars each and converted into binary. How do you turn it into its 64-bit int value?
s = 'Q\xcb\x80\x80\x00\x00\x01\x9bQ\xcc\xd2\x00\x00\x00\x01\x9b'
date_chunk = s[0:8]
value_chunk = s[8:]
Looks like hex now that I got it to print. How do I make two ints? The first is a date encoded to seconds since epoch.
The struct module unpacks binary. Use qq for signed ints.
>>> s = 'Q\xcb\x80\x80\x00\x00\x01\x9bQ\xcc\xd2\x00\x00\x00\x01\x9b'
>>> len(s)
16
>>> import struct
>>> struct.unpack('>QQ',s) # big-endian
(5893945824588595611L, 5894316909762970011L)
>>> struct.unpack('<QQ',s) # little-endian
(11169208553011465041L, 11169208550869355601L)
You also mentioned an original 8 hex chars. Use the binascii.unhexlify function in that case. Example:
>>> s = '11223344'
>>> import binascii
>>> binascii.unhexlify(s)
'\x11"3D'
>>> struct.unpack('>L',binascii.unhexlify(s))
(287454020,)
>>> hex(287454020)
'0x11223344'
import struct
struct.unpack(">QQ",s)
Or
struct.unpack("<QQ",s)
Depending on the endianness of the machine that generated the bytes

convert from string object to binary value python

I have a string that hold a binary number as a string
string = '0b100111'
I want to have that value not be a string type but a value (pseudo-code)
bin(string) = 0b100111
Any pythoners know an easy way to do this?
It is all part of this code for a Codecademy: (After answer implemented)
def flip_bit(number,n):
if type(number)==type('s'):
number = int(number,2)
mask=(0b1<<n-1)
print bin(mask)
print mask
desired = bin(number^mask)
return desired
flip_bit('0b111', 2)
What about calling int function with base 2?
>>>s = '0b100111'
>>>b = int(s, 2)
>>>print b
39
you can make it binary by putting a b before the quotes:
>>> s = b'hello'
>>> s.decode()
'hello'
I'm afraid that making it as idealised in your question is impossible. As what you want is a a series of characters, it can only be a string (or you could convert it to an integer). But it is still workable as a number with built in functions- for example:
num1 = '0b0110'
num1 = '0b0101'
result = int(num1, 2) + int(num2, 2)
print(bin(result))
The only way you could have that synatx in your code is if that binary number became a name itself. Python only supports the manipulation of numbers in base 10, as it only interprets number inputs in that format. Otherwise it is a string within which numbers cannot be manipulated.

Convert int to single byte in a string?

I'm implementing PKCS#7 padding right now in Python and need to pad chunks of my file in order to amount to a number divisible by sixteen. I've been recommended to use the following method to append these bytes:
input_chunk += '\x00'*(-len(input_chunk)%16)
What I need to do is the following:
input_chunk_remainder = len(input_chunk) % 16
input_chunk += input_chunk_remainder * input_chunk_remainder
Obviously, the second line above is wrong; I need to convert the first input_chunk_remainder to a single byte string. How can I do this in Python?
In Python 3, you can create bytes of a given numeric value with the bytes() type; you can pass in a list of integers (between 0 and 255):
>>> bytes([5])
b'\x05'
bytes([5] * 5)
b'\x05\x05\x05\x05\x05'
An alternative method is to use an array.array() with the right number of integers:
>>> import array
>>> array.array('B', 5*[5]).tobytes()
b'\x05\x05\x05\x05\x05'
or use the struct.pack() function to pack your integers into bytes:
>>> import struct
>>> struct.pack('{}B'.format(5), *(5 * [5]))
b'\x05\x05\x05\x05\x05'
There may be more ways.. :-)
In Python 2 (ancient now), you can do the same by using the chr() function:
>>> chr(5)
'\x05'
>>> chr(5) * 5
'\x05\x05\x05\x05\x05'
In Python3, the bytes built-in accepts a sequence of integers. So for just one integer:
>>> bytes([5])
b'\x05'
Of course, thats bytes, not a string. But in Python3 world, OP would probably use bytes for the app he described, anyway.

Categories