简体   繁体   English

将 Python 十六进制字符串解析为两半

[英]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.我正在尝试使用 python len() 函数来查找总长度,将其除以一半,然后使用 [:middle value] 分割字符串的前半部分和 [middle value:] 的第二部分。 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.所以这就是我的困惑所在。规则说 #0-799 加载数据,每个 4 个字节和 #800-1599 位置数据,每个 4 个字节。 When I split the string on "middle_of_string" i get equal numbers on both sides.当我在“middle_of_string”上拆分字符串时,两边的数字都相等。 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.看起来 len() 函数计算元素而不是索引,因此不是从零开始的。 However, the rules are obviously 0 based.但是,规则显然是基于 0 的。

I'm a newby at python and been staring at this too long so any help would be appreciated.我是 python 的新手,一直盯着这个太久了,所以任何帮助都将不胜感激。

When I split the string on "middle_of_string" i get equal numbers on both sides.当我在“middle_of_string”上拆分字符串时,两边的数字都相等。 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是一个 1600 个字符的字符串,那么:

s[:800] means all the elements before but not including 800. That's elements 0 through 799 inclusive. s[:800]表示之前的所有元素,但不包括800。即元素 0 到 799(包括 0 到 799)。

s[800:] means all the elements from 800 onwards, including 800. That's elements 800 through 1599 inclusive. s[800:]表示从 800 开始的所有元素,包括800。即从 800 到 1599 的元素。

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.您可以在两个表达式中使用相同的索引 800 来划分字符串,而不会遗漏或重复。

And it appears that the len() function counts elements and not index.似乎 len() 函数计算元素而不是索引。

Yes, if you have a 1600-character string s then the final character is s[1599] but len(s) == 1600 .是的,如果你有一个 1600 个字符的字符串s那么最后一个字符是s[1599]len(s) == 1600

From the Python documentation :Python 文档

The built-in function len() returns the number of items of a sequence.内置函数 len() 返回序列的项目数。 When the length of a sequence is n, the index set contains the numbers 0, 1, …, n-1.当序列的长度为 n 时,索引集包含数字 0、1、…、n-1。 Item i of sequence a is selected by a[i].序列 a 的项目 i 由 a[i] 选择。

Sequences also support slicing: a[i:j] selects all items with index k such that i <= k < j.序列也支持切片:a[i:j] 选择索引为 k 的所有项目,使得 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.这意味着索引集被重新编号,使其从 0 开始。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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