1

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)

寄存器值的一个例子是;

寄存器 1;16282 寄存器 2;60597

这会产生结果浮点数

1.21034872532

一个完美的数字,但有时内存值类似于;

寄存器 1;16282 寄存器 2;1147

其中,使用此函数会导致浮点数;

1.46726675314e-36

这是一个非常小的数字,而不是一个看似正确的数字。该设备应产生 1.2、1.3 范围内的读数。

我要解决的是设备是否抛出虚假值,或者我得到的值是否正确但我使用的函数无法正确转换它们。

还有没有更好的方法来做到这一点,比如 numpy 或类似的东西?我会举手说我刚刚从网上的示例中复制了这段代码,我对它的工作原理知之甚少,但它似乎在我当时可用的测试用例中工作。

谢谢你。

4

2 回答 2

7

如果您有原始字节(例如,从内存、文件、网络中读取,...),您可以使用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
于 2013-01-23T22:56:52.433 回答
1

您转换两个 s 的方式隐含了我认为错误的字节顺序int假设。

所以,让我们后退一步。你知道第一个参数是最重要的词,第二个是最不重要的词。所以,与其试图弄清楚如何以适当的方式将它们组合成一个十六进制字符串,不如让我们这样做:

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
于 2013-01-23T23:09:14.883 回答