我正在寻找python中的一种方法,对二进制数进行右移和位掩码,二进制数也有一个小数部分。例如,如果数字中有1个整数和2个分数位,则数字0b101对应于十进制的1.25。首先,我想知道在python中表示这个数字的pythonic方法。
其次,我想对此数字执行1次右移(0b101>> 1),以便得到的数字为0b010,十进制为0.5。在python中是否有一种内在的和pythonic方式来执行此操作。同样,如何从二进制数掩码并获取特定位?
目前,对于班次我将数字乘以2 ** - x,x是右移的数量。我无法想到我可以为位掩码执行类似的操作。
答案 0 :(得分:1)
如果你真的必须直接获得浮动的内部表示,你可以使用struct
,如下所示:
>>> import struct
>>> a = 1.25
>>> b = struct.pack('>d',a)
>>> b
b'?\xf4\x00\x00\x00\x00\x00\x00' # the ? means \x3f, leftmost 7 bits of exponent
>>> a.hex()
'0x1.4000000000000p+0'
您可以从struct.pack()
返回的字节串中屏蔽您想要的位。
[edit] 表示\x3f
的问号是因为bytestring的默认输出表示是 string ,Python会尽可能显示ascii字符,不是两个十六进制数字。
[edit] 这种表示原则上依赖于平台,但实际上并不是这样,因为几乎每台计算机(现在甚至是IBM大型机)都有一个使用的浮点处理器这种格式。
找出你想要的位可能是一个挑战。
>>> c = struct.pack('>d',a/2)
>>> c
b'?\xe4\x00\x00\x00\x00\x00\x00'
>>> (a/2).hex()
'0x1.4000000000000p-1'
正如你所看到的那样,除非你的问题似乎表明你期待的是一个简单的一位向右移动。在这种情况下,除以2将指数递减1(从0x3ff
递减到0x3fe
;将1023递减到1022)并保持分数(0x4000
)的位模式不变。指数看起来很大,因为它偏向1023。
主要困难是
我可以就这个问题推荐Wikpedia article:它有很多有用的例子。
但我怀疑你并不想真正想要浮动的内部代表。相反,你想要一个 fixed -point二进制类,没有讨厌的二进制指数,它的工作方式与你在纸上的工作方式大致相同,并且2的幂除法确实反映为一个移位右边那么多位。
根据您想要投入多少工作,您可以通过将FixedBinary
类定义为numbers.Real
的子类来实现此目的,其中整数部分由一个{{1}内部表示}和另一个int
的小数分量,以及第三个int
的符号,因此1.25将表示为int
(或其他一些2的幂)。
这也向您展示了获得分数表示的最简单方法。
[edit] 我建议单独存储标志。您可以将它存储在整数部分或分数或两者中,但都有缺点。
65536的被乘数将为您提供4位小数的精度。如果您想要更多,可以增加它。我还建议您将分数存储在最右边的位中,然后忽略最左边的位。换句话说,要满足于(1, int(0.25 * 65536), +1)
中间的二进制点,不要坚持它在左边。这是因为当你进行乘法运算时,你需要在二进制点左边的余量。
但是,实现自己的数字类是相当多的工作。
答案 1 :(得分:1)
您可以使用fxpmath进行工作。
有关此软件包的信息位于: https://github.com/francof2a/fxpmath
以您的示例为例:
from fxpmath import Fxp
x = Fxp('0b0101', signed=True, n_word=4, n_frac=2)
print(x)
y = x >> 1
print(y)
# example of AND mask
z = x & Fxp('0b0110', signed=True, n_word=4, n_frac=2)
print(z.bin())
输出:
1.25
0.5
0100