I'm trying to turn a string representing a Hexidecimal number into an int in python without using the int constructor.
For example if I was given
hexstring = "802"
How would I get that to be
output = 2050
Without doing
int("802",16)
How would I go about this?
hexstring = "802"
L=len(hexstring)
def val(h_char):
# Note you need to extend this to make sure the lowercase hex digits are processed properly
return ord(h_char)- (55 if ord(h_char)>64 else 48)
def sumup(sum,idx):
global hexstring # global variables are not recommended
L=len(hexstring)
return sum + 16**idx*val(hexstring[L-idx-1])
output = reduce(lambda a,b:sumup(a,b),range(L),0))
Below is just an explanation of the above and doesn't add any value
Processes on a list of [0,1,2] produced by range(L).
For each idx from above list a function call is made as sumup(sum, idx)=sum+16^idx*h_digit_at_idx.(^ is ** is exp in above)
h_digit_at_idx = ord(h_char)- (55 if ord(h_char)>64 else 48)
ord(h_char) produces 48,49...57,65,66,67,68,69,70 for hex characters 0,1...10,A,B,C,D,E,F
ord(h_char)-(55 if ord(h_char)>64 else 48 produces 0,1...10,11,12,13,14,15 for respective chars.
Finally the last argument of the reduce function is 0(which is the initial sum to start with)
Related
I want to combine two bytes (8 bit) to form a signed value (one bit for sign and 15 for the value) according to the two complement's method.
I receive MSbyte (note that the most left bit of MSByte is for the sign) and the LSbyte. So I write a function by shifting the MSByte to the left by 8 bit then I add it with the LSByte to form a binary sequence of 16 bit. Then, I calculate the ones'complement, and I finally add 1 to the result. However, it does not work.
def twos_comp_two_bytes(msb, lsb):
a= (msb<<8)+ lsb
r = ~(a)+1
return r
For example 0b0b1111110111001001 is -567 however with the above function I get -64969.
EDIT : call of the function
twos_comp_two_bytes(0b11111101,0b11001001) => -64969
Python uses integers which may have any lenght - they are not restricted to 16bits so to get -567 it would need rather
r = a - (256*256)
but it need more code for other values
def twos_comp_two_bytes(msb, lsb):
a = (msb<<8) + lsb
if a >= (256*256)//2:
a = a - (256*256)
return a
print(twos_comp_two_bytes(0b11111101, 0b11001001))
print(twos_comp_two_bytes(0b0, 0b0))
print(twos_comp_two_bytes(0b0, 0b1))
print(twos_comp_two_bytes(0b10000000, 0b0))
print(twos_comp_two_bytes(0b10000000, 0b1))
Results:
-567
0
1
-32768
-32767
It would be better to use special module struct for this
import struct
def twos_comp_two_bytes(msb, lsb):
return struct.unpack('>h', bytes([msb, lsb]))[0]
#return struct.unpack('<h', bytes([lsb, msb]))[0] # different order `[lsb, msb]`
#return struct.unpack( 'h', bytes([lsb, msb]))[0] # different order `[lsb, msb]`
print(twos_comp_two_bytes(0b11111101, 0b11001001))
print(twos_comp_two_bytes(0b0, 0b0))
print(twos_comp_two_bytes(0b0, 0b1))
print(twos_comp_two_bytes(0b10000000, 0b0))
print(twos_comp_two_bytes(0b10000000, 0b1))
Results:
-567
0
1
-32768
-32767
Letter h means short integer (signed int with 2 bytes).
Char >, < describes order of bytes.
See more in Format Characters
I want to "unpack" OR de-serialize the formatted data that is outputed from python's struct.pack() function. The data is sent over the network to another platform that uses Java only.
The Python function that sends data over the network, uses this formater:
def formatOutputMsg_Array(self, mac, arr):
mac_bin = mac.encode("ascii");
mac_len = len(mac_bin);
arr_bin = array.array('d', arr).tobytes();
arr_len = len(arr_bin);
m = struct.pack('qqd%ss%ss' % (mac_len, arr_len), mac_len, arr_len, time.time(), mac_bin, arr_bin);
return m
Here are the docs for python's struct (refer to section 7.3.2.2. Format Characters):
https://docs.python.org/2/library/struct.html
1) The issue is what does 'qqd%ss%ss' mean ???
Does it mean -> long,long,double,char,char,[],char[],char,char[],char[]
2) why is modulo "%" used here with a tuple 'qqd%ss%ss' % (mac_len, arr_len) ?
The first argument to pack is the result of the expression 'qqd%ss%ss' % (mac_len, arr_len), where the two %s are replaced by the values of the given variables. Assuming mac_len == 8 and arr_len == 4, for example, the result is qqd8s4s. s preceded by a number simply means to copy the given bytes for that format into the result.
I have a python function called read_memory that has one parameter that is called addr. I want to implement a way to convert the addr to HEX value. It sounds simple but the user can enter either a string/int in the parameter:
read_memory(0x106940)
read_memory('0x106940')
read_memory(106940) #this is an int
read_memory('106940')
The result should all be 0x106940. I have the following code but it does not work as expected:
def read_memory(addr):
hex_addr = str(addr)
if('0x' not in hex_addr):
hex_addr = '0x' + hex_addr
return hex_addr
The results are:
read_memory(0x106940) -> 0x1075520
read_memory('0x106940') -> 0x106940
read_memory(106940) -> 0x106940
read_memory('106940') -> 0x106940
Any help is appreciate.
I don't think it is such a great idea to have your function accept int
in base 10 and int in base 16 indiscriminately; this will hurt you
down the road. The following treats proposal treats the input as it is,
instead of "as it should be".
You could use a try except block to control the flow:
def read_memory(addr):
try:
return hex(addr)
except TypeError:
str_addr = str(addr)
if('0x' != str_addr[:2]):
hex_addr = '0x' + str_addr
else:
hex_addr = str_addr
return hex_addr
print(read_memory(0x106940)) # a hex (int base 16)
print(read_memory('0x106940')) # a string representing a hex
print(read_memory(106940)) # an integer (int base 10)
print(read_memory('106940')) # a string representing a hex
The results are:
0x106940
0x106940
0x1a1bc # <-- this is the hex value of integer 106940
0x106940
Specifically in Python 2.4, which is unfortunately old, I need to convert a length into hex value. Length of 1 would be '\x00\x01' while a length of 65535 would be '\xFF\xFF'.
import struct
hexdict = {'0':'\x00\x00', '1':'\x00\x01', '2':'\x00\x02', '3':'\x00\x03', '4':'\x00\x04', '5':'\x00\x05', '6':'\x00\x06', '7':'\x00\x07', '8':'\x00\x08', '9':'\x00\x09', 'a':'\x00\x0a', 'b':'\x00\x0b', 'c':'\x00\x0c', 'd':'\x00\x0d', 'e':'\x00\x0e', 'f':'\x00\x0f'}
def convert(int_value): # Not in original request
encoded = format(int_value, 'x')
length = len(encoded)
encoded = encoded.zfill(length+length%2)
retval = encoded.decode('hex')
if x < 256:
retval = '\x00' + retval
return retval
for x in range(16):
print hexdict[str(hex(x)[-1])] # Original, terrible method
print convert(x) # Slightly better method
print struct.pack(">H", x) # Best method
Aside from having a dictionary like above, how can I convert an arbitrary number <= 65535 into this hex string representation, filling 2 bytes of space?
Thanks to Linuxios and an answer I found while waiting for that answer, I have found three methods to do this. Obviously, Linuxios' answer is the best, unless for some reason importing struct is not desired.
Using Python's built-in struct package:
import struct
struct.pack(">H", x)
For example, struct.pack(">H", 1) gives '\x00\x01' and struct.pack(">H", 65535) gives '\xff\xff'.
I am trying to convert the following code from c to Python. The C code looks like:
seed = (time(0) ^ (getpid() << 16));
fprintf("0x%08x \n", seed);
that outputs values like 0x7d24defb.
And the python code:
time1 = int(time.time())
seed = (time1 ^ (os.getpid() <<16))
that outputs values like: 1492460964
What do i need to modify at the python code so I get address-like values?
It depends on the way the value is displayed. The %x flag in printf-functions displays the given value in hexadecimal. In Python you can use the hex function to convert the value to a hexadecimal representation.
The equivalent Python code to: fprintf("0x%08x \n", seed);
>>> '0x{:08x}"'.format(1492460964)
'0x58f525a4"'
Note that hex() alone won't pad zeros to size 8 like the C code does.
I suppose this is what you what:
>>> n =hex (int(time.time()) ^ (os.getpid() <<16))
>>> print n
0x431c2fd2
>>>