我需要一个函数将浮点数转换为以二进制表示的定点数,以便我可以将其放入只能接受定点数的硬件加速器中。例如,当我输入浮点数 5.625 时,数据宽度为 8,精度为 4(尾数为 4 位),它将返回 b'01011010,或 h'5a 或 d'90。 python库中有类似的函数吗?
这与乘以 16 并转换为 int 相同。
>>> int(5.625 * (2 ** 4))
90
16取决于精度的位数,但很容易计算。
如果数字必须包含多个字节(例如 2 或 4),请使用
struct
模块。例如。对于 300.625,有 32 个数据位,其中 8 个是精度:
>>> int(300.625 * (2**8))
76960
>>> struct.pack('I', 76960) # 'I' is 4-byte unsigned int
b'\xaa,\x01\x00'
您可以在Python中使用fxpmath。您可以在以下位置找到相关信息:
https://github.com/francof2a/fxpmath
在您的示例中:
from fxpmath import Fxp
x = Fxp(5.625, signed=False, n_word=8, n_frac=4)
print(x) # float value
print(x.bin()) # binary representation
print(x.hex()) # hex repr
print(x.val) # raw val (decimal of binary stored)
输出:
5.625
01011010
0x5a
90
一些定点库如numfi可以将浮点数转换为定点并给出bin/dec/hex表示
>>> from numfi import numfi
>>> x = numfi(5.625,1,8,4)
>>> x.int # d'90
array([90], dtype=int64)
>>> x.bin # b'01011010
array(['01011010'], dtype='<U8')
>>> x.hex # h'5a
array(['5A'], dtype='<U2')
如果您喜欢更简单的解决方案,您可以自己进行量化:
num = 5.625
w = 8 # data width
f = 4 # fraction width
quantized = np.round(num*(2**f)).astype(int) #note: overflow is not considered here
dec_repr = np.base_repr(quantized, base=10)
bin_repr = np.binary_repr(quantized, width=8)
hex_repr = np.base_repr(quantized, base=16)
尝试使用decimal模块。
您可以向其传递一个具有所需格式和精度的字符串格式的浮点数:
>>> from decimal import Decimal
>>> '{:5f}'.format(10.0)
'10.000000'
>>> Decimal('{:5f}'.format(10.0))
Decimal('10.000000')
def float2fix(val, width, precision):
integer = abs(int(val * 2 ** precision))
if val < 0:
integer = 2 ** (width-1) - integer
if val >= 0:
fix_str = bin(integer).replace('0b', '').rjust(width, '0')
else:
fix_str = '1'+bin(integer).replace('0b', '').rjust(width-1, '0')
return fix_str
这个fixed_8_to_float函数旨在根据用户francof2a提供的实现将固定int8转换回浮点表示形式
from fxpmath import Fxp
def fixed_8_to_float(binary):
sum = 0
multi = 4
for i in range(1,8):
sum = sum + int(binary[i]) * multi
multi/= 2
if(int(binary[0])==1):
sum-=8
return sum
floating_nums = [1 , -1, 2.34,-2.4,-8,0.42]
fixed_nums = [Fxp(x, signed=True, n_word=8, n_frac=4) for x in floating_nums]
binary_strings = [str(x.bin()) for x in fixed_nums]
hex_strings = [str(x.hex()) for x in fixed_nums ]
print(floating_nums)
print(binary_strings)
print(hex_strings)
print([fixed_8_to_float(x) for x in binary_strings])
输出:
[1,-1,2.34,-2.4,-8,0.42]
['00010000', '11110000', '00100101', '11011010', '10000000', '00000110']
['0x10'、'0xF0'、'0x25'、'0xDA'、'0x80'、'0x06']
[1.0,-1.0,2.3125,-2.375,-8.0,0.375]