Redhat 6.3上的Python 2.6
我有一个器件可以在2个存储器寄存器中保存32位浮点值,分成最重要的字和最低有效字。 我需要将其转换为浮点数。 我一直在使用SO上的以下代码,它类似于我在别处看到的代码
#!/usr/bin/env python
import sys
from ctypes import *
first = sys.argv[1]
second = sys.argv[2]
reading_1 = str(hex(int(first)).lstrip("0x"))
reading_2 = str(hex(int(second)).lstrip("0x"))
sample = reading_1 + reading_2
def convert(s):
i = int(s, 16) # convert from hex to a Python int
cp = pointer(c_int(i)) # make this into a c integer
fp = cast(cp, POINTER(c_float)) # cast the int pointer to a float pointer
return fp.contents.value # dereference the pointer, get the float
print convert(sample)
寄存器值的一个例子是;
register-1; 16282 register-2; 60597
这会产生
的浮点数1.21034872532
一个完美的数字,但有时候内存值就像是;
register-1; 16282 register-2; 1147
,使用此函数会导致浮动;
1.46726675314e-36
这是一个非常小的数字,而不是一个似乎正确的数字。该设备应在1.2,1.3范围内产生读数。
我想解决的问题是,如果设备正在冒伪造价值,或者我得到的值是否正确,但我使用的功能无法正确转换它们。
还有更好的方法来做到这一点,比如numpy或那种性质的东西? 我会举起手来说我刚从示例中复制了这些代码并且我对它的工作原理知之甚少,但它似乎适用于我当时可用的测试用例。 / p>
谢谢。
答案 0 :(得分:5)
如果您有原始字节(例如从内存中读取,从文件中读取,通过网络读取......),您可以使用struct
:
>>> import struct
>>> struct.unpack('>f', '\x3f\x9a\xec\xb5')[0]
1.2103487253189087
这里,\x3f\x9a\xec\xb5
是您的输入寄存器,16282(十六进制0x3f9a)和60597(十六进制0xecb5)表示为字符串中的字节。 >
是字节顺序标记。
因此,根据您获取寄存器值的方式,您可以使用此方法(例如,将输入整数转换为字节字符串)。您也可以使用struct
;这是你的第二个例子:
>>> raw = struct.pack('>HH', 16282, 1147) # from two unsigned shorts
>>> struct.unpack('>f', raw)[0] # to one float
1.2032617330551147
答案 1 :(得分:1)
您转换这两个int
的方式会对我认为错误的endianness做出隐含的假设。
所以,让我们退一步吧。你知道第一个参数是最重要的词,第二个是最不重要的词。所以,不要试图弄清楚如何以适当的方式将它们组合成十六进制字符串,让我们这样做:
import struct
import sys
first = sys.argv[1]
second = sys.argv[2]
sample = int(first) << 16 | int(second)
现在我们可以像这样转换:
def convert(i):
s = struct.pack('=i', i)
return struct.unpack('=f', s)[0]
如果我在你的输入上尝试:
$ python floatify.py 16282 60597
1.21034872532
$ python floatify.py 16282 1147
1.20326173306