我以numpy格式浮动32个数字(让我们说正数)。我想将它们转换为具有预定义位数的定点数,以降低精度。
例如,使用函数num2fixpt,数字3.1415926在matlab中变为3.25。 该命令是num2fixpt(3.1415926,sfix(5),2 ^(1 + 2-5),' Nearest',' on')其中3位表示整数部分,2位小部分。
我可以使用Python
做同样的事情答案 0 :(得分:3)
如果您了解IEEE浮点表示法的工作原理,则可以执行此操作。基本上你需要转换为python LONG,执行按位运算符,然后再转换回来。例如:
import time,struct,math
long2bits = lambda L: ("".join([str(int(1 << i & L > 0)) for i in range(64)]))[::-1]
double2long = lambda d: struct.unpack("Q",struct.pack("d",d))[0]
double2bits = lambda d: long2bits(double2long(d))
long2double = lambda L: struct.unpack('d',struct.pack('Q',L))[0]
bits2double = lambda b: long2double(bits2long(b))
bits2long=lambda z:sum([bool(z[i] == '1')*2**(len(z)-i-1) for i in range(len(z))[::-1]])
>>> pi = 3.1415926
>>> double2bits(pi)
'0100000000001001001000011111101101001101000100101101100001001010'
>>> bits2long('1111111111111111000000000000000000000000000000000000000000000000')
18446462598732840960L
>>> double2long(pi)
4614256656431372362
>>> long2double(double2long(pi) & 18446462598732840960L)
3.125
>>>
def rshift(x,n=1):
while n > 0:
x = 9223372036854775808L | (x >> 1)
n -= 1
return x
>>> L = bits2long('1'*12 + '0'*52)
>>> L
18442240474082181120L
>>> long2double(rshift(L,0) & double2long(pi))
2.0
>>> long2double(rshift(L,1) & double2long(pi))
3.0
>>> long2double(rshift(L,4) & double2long(pi))
3.125
>>> long2double(rshift(L,7) & double2long(pi))
3.140625
这只会截断位数,而不是围绕它们。 rshift函数是必要的,因为python的右移运算符用零填充空的最左位。请参阅IEEE浮点here的描述。
答案 1 :(得分:1)
您可以舍入到二进制固定精度,而无需显式类型转换,这往往会产生大量的解释器开销:
import numpy as np
n_bits = 2
f = (1 << n_bits)
a = np.linspace(1, 2, 11)
a_fix = np.round(a*f)*(1.0/f)
print a
print a_fix
结果
[ 1. 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2. ]
[ 1. 1. 1.25 1.25 1.5 1.5 1.5 1.75 1.75 2. 2. ]
该示例使用numpy,但这只是为了方便生成示例值列表。 Python的内置round
也适用于单个值:
x=3.1415926
x_fix = round(x*f)/float(f)
print x_fix
注意f和1.0 / f都有精确的浮点表示;因此,乘法和除法是精确的,没有舍入误差。另请注意,乘以1.0/f
比在大型数组中直接划分快3倍。
这种方法不能控制整数部分的位数,所以如果你想要数字上限或者如果它们太大则需要回绕,那么你必须做更多的位移。
答案 2 :(得分:0)
您可以使用 fxpmath 模块在python中使用分数定点。
模块存储库:https://github.com/francof2a/fxpmath
from fxpmath import Fxp
pi_fxp = Fxp(None, signed=False, n_word=5, n_frac=2) # create fixed-point object (3 bit for intefer, 2 for fractional)
pi_fxp.rounding = 'around' # define rounding method, default is `trunc`.
pi_fxp(3.1415926) # set value
print(pi_fxp) # printed value = 3.25