简体   繁体   中英

Parsing Python hex string in half

I'm having troubles wrapping my head around splitting this hex string by the following request.

#hex string byte layout Description
#0-799 Load data, 4 bytes each
#800-1599 Position data, 4 bytes each
#leading 0x has been removed

I am attempting to use the python len() function to find the total length, dividing it by half, then splitting the string using [:middle value] for the first half and [middle value:] for the second. This is my code.

#INSERT LIBRARIES
import matplotlib.pyplot as plt

#this hex string is from the sample given by theta

hex_string = '00706A450090574500F0484500C0394500802D45001027450050284500E0304500603E4500204D450010594500C05E4500505C4500F051450060414500C02D4500E01A4500C00C4500C0064500000B4500D019450060314500E04D4500006A450008804500A08545007884450030794500205F4500E03F4500D0214500F00A450080FF440070024500D0124500202E450060504500F0744500D08B4500009B4500A0A7450040B24500F8BB4500F0C54500D0D0450080DC450028E8450068F2450000FA450028FE4500D8FE4500F0FC4500B8F9450088F6450068F44500D8F34500C8F44500B8F6450028F94500A0FB4500F0FD45000C0046002401460058024600B803460038054600B8064600F4074600980846005C08460010074600B40446009001460050FC450040F6450048F2450068F1450020F4450040FA45006C01460044064600BC0A4600F80D4600280F4600CC0D4600B409460010034600C0F44500D0E04500F8CB4500C8B7450090A5450038964500308A45009881450060784500B072450010704500206E4500706A45000000005C8F0240D7A380408FC2CD409A9911413D0A3F4152B86E4152B89041F628AC41713DCA41A470EB413D0A08427B141C42CDCC314285EB4842C3F56042B81E79420A578842856B93423D8A9D4214AEA6420000AF42ECD1B6425C8FBE423D8AC6425C0FCF425238D8420000E2423333EC42E17AF64252380043ECD104439AD9084333330C43D7E30E43CD0C114348E11243299C1443146E1643D7631843146E1A43856B1C43A4301E43B89E1F43F6A82043B85E214329DC21431F45224385AB22430A1723435278234314AE23439A9923437B1423437B1422435C8F20437B941E4333331C438F821943CD8C16430A5713439AD90F433D0A0C4366E60743A4700343C375FD4214AEF34252B8E94252B8DF4271BDD542CDCCCB4285EBC1427B14B8428F42AE42A470A44200809A42CD4C9042F6A88542B81E75427B145E420AD74642F628304285EB1A4252B807429A99ED410000D0418FC2B5410AD79D410AD787413D0A6741713D4241A4702141EC5104413333D3400000A040CDCC5C4000000040295C4F3F0AD7A33D00000000'

#Signed Integer: A 16-bit signed integer ranging from -32,768 to +32,767
#Unsigned Integer: A 16-bit unsigned integer ranging from 0 to 65535. 
#signed 32 bit int range is -2147483648 to 2147483647
#unsigned 32 int range is 0 to 4294967295

#sampe hex string:#5C8F0240
#Converted 32 bit equivalent: 1552876096

#Card hex string byte layout Description

#0-799 Load data, 4 bytes each
#800-1599 Position data, 4 bytes each

#create a new function that scales the 32 bit unsigned integer position value into a float value. Assuming a stroke range of 0-168 inches and that the integer value is unsigned 32 bit
def u32int_pos_to_float(u32int_value):
    OldValue = u32int_value
    OldMin = 0
    OldMax = 4294967295
    NewMin = 0
    NewMax = 168
    NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
    return NewValue

#create a new function that scales the 32 bit unsigned integer load value into a float value. Assuming a load cell of 0-30000 lbs and that the integer value is unsigned 32 bit
def u32int_load_to_float(u32int_value):
    OldValue = u32int_value
    OldMin = 0
    OldMax = 4294967295
    NewMin = 0
    NewMax = 30000
    NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
    return NewValue

#Card hex string byte layout Description

#0-799 Load data, 4 bytes each
#800-1599 Position data, 4 bytes each

#A byte (or octet) is 8 bits so is always represented by 2 Hex characters in the range 00 to FF
#4 bytes = 32 bits

#Find the middle index of the hex_string and split the string into two halves

print(' ')
print('-----this is the start of the hex string conversion logic-----')
print(' ')
print('The hex string is: ' + hex_string)
print(' ')
print('hex string length: ' + str(len(hex_string)))
middle_of_String = int(len(hex_string)/2)
print('middle of string is:',middle_of_String,)
lastloadinstring = middle_of_String
startposinstring = middle_of_String

print('')
hex_load_string = hex_string[:lastloadinstring]
print(len(hex_load_string))
hex_pos_string = hex_string[startposinstring:]
print(len(hex_pos_string))

print(' ')
print('----Start of the hexadecial load and position lists from Hex String dividing in half----')
print(' ')
print('hex_load_string length:',len(hex_load_string))
print(hex_load_string)
print('hex_pos_string length:',len(hex_pos_string))
print(hex_pos_string)

#parse the hex strings into 4 byte chunks
hex_load_list = [hex_load_string[i:i+8] for i in range(0, len(hex_load_string), 8)]
hex_pos_list = [hex_pos_string[i:i+8] for i in range(0, len(hex_pos_string), 8)]

print(' ')
print('---start of the hexadecimal load and position 4 byte "chunks" list----')
print('----Note from developer: 0-799 Load data and 800-1599 Position data are 4 bytes each----')
print(' ')
print('hex_load_list length:',len(hex_load_list))
print(hex_load_list)
print('hex_pos_list length:',len(hex_pos_list))
print(hex_pos_list)

#convert each hex chunk to 32 bit unsigned integer
load_list_int = []
pos_list_int = []
for i in range(0, len(hex_load_list)):
    load_list_int.append(int(hex_load_list[i],16))
    pos_list_int.append(int(hex_pos_list[i],16))

print(' ')
print('----start of the load and position unsigned 32 bit integer list----')
print(' ')
print('load_list_int length:',len(load_list_int))
print(load_list_int)
print('pos_list_int length:',len(pos_list_int))
print(pos_list_int)

#using the new function, convert the 32 bit unsigned integers to a new list of floats

load_list_float = []
for i in range(0, len(load_list_int)):
    load_list_float.append(u32int_load_to_float(load_list_int[i]))

pos_list_float = []
for i in range(0, len(pos_list_int)):
    pos_list_float.append(u32int_pos_to_float(pos_list_int[i]))

print(' ')
print('----start of the load and position floating value lists----')
print('--these are scaled using the functions are the top of the code. All scaled as unsigned 32 bit integers---')
print('---engineering units for scaling in function comments-----')
print(' ')
print('load_list_float length:',len(load_list_float))
print(load_list_float)
print('pos_list_float length:',len(pos_list_float))
print(pos_list_float)

#create a scatter plot of the position and load data
plt.scatter(pos_list_float, load_list_float)
plt.xlabel('Position (inches)')
plt.ylabel('Load (lbs)')
plt.title('Position vs Load')
plt.show()

So this is where my confusion comes in. The rule says #0-799 Load data, 4 bytes each and #800-1599 Position data, 4 bytes each. When I split the string on "middle_of_string" i get equal numbers on both sides. Does this mean that I am duplicating the last value of the first half and the first value of the second half? And it appears that the len() function counts elements and not index therefore not zero based. However, the rules are obviously 0 based.

I'm a newby at python and been staring at this too long so any help would be appreciated.

When I split the string on "middle_of_string" i get equal numbers on both sides. Does this mean that I am duplicating the last value of the first half and the first value of the second half?

No! You're dividing the string exactly in half correctly. Assuming s is a 1600-character string then:

s[:800] means all the elements before but not including 800. That's elements 0 through 799 inclusive.

s[800:] means all the elements from 800 onwards, including 800. That's elements 800 through 1599 inclusive.

This is often confusing to beginners, but your code is actually a good example of why it was defined that way. You can use the same index 800 in both expressions, to divide the string without omission or duplication.

And it appears that the len() function counts elements and not index.

Yes, if you have a 1600-character string s then the final character is s[1599] but len(s) == 1600 .

From the Python documentation :

The built-in function len() returns the number of items of a sequence. When the length of a sequence is n, the index set contains the numbers 0, 1, …, n-1. Item i of sequence a is selected by a[i].

Sequences also support slicing: a[i:j] selects all items with index k such that i <= k < j. When used as an expression, a slice is a sequence of the same type. This implies that the index set is renumbered so that it starts at 0.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM