import numpy as np
from fxpmath import Fxp as fxp
t1 = fxp(4, False, 9, 3)
t2 = fxp(5, False, 9, 3)
inter1 = fxp(0, True, 9, 3, raw=True)
inter2 = fxp(0, True, 9, 3, raw=True)
inter1(t1 - t2)
inter2(t1.get_val() - t2.get_val())
inter1 等于 0.00,因为计算中使用的两个数字都是无符号的。我发现获得正确结果的唯一方法是使用 numpy 值(来自 get_val())。有没有最好的方法来做到这一点?我不想将 t1 或 t2 带符号。
@jasonharper 提出的解决方案是正确的,但它可能不是您想要建模的。
当你这样做时:
t1.like(inter1) - t2.like(inter1) # t1_signed - t2_signed
fxp-s10/3(-1.0)
您正在将
t1
和 t2
转换为 signed 就像 inter1
一样,所以您正在执行 signed 减法,我认为这不是您想要建模的。
将无符号 fxp 转换为有符号,将 msb(最高有效位)强制转换为
0
(如果保持大小)。如果 t1
和/或 t2
等于或大于 有符号上限(对于您的示例为 31.875),这将生成错误的计算。例如:
t3 = fxp(48, False, 9, 3)
t4 = fxp(49, False, 9, 3)
t3.like(inter1) - t4.like(inter1) # t3_signed - t4_signed
# t3_signed = fxp-s9/3(31.875) because overflow clipping
# t4_signed = fxp-s9/3(31.875) because overflow clipping
fxp-s10/3(0.0)
如果您尝试建模无符号减法,然后将该值存储在有符号 fxp 中,则必须使用wrap 溢出。另外,如果你想将大小保持在减法(或其他操作),你必须设置
op_sizing = 'same'
:
t1 = fxp(4, False, 9, 3, overflow='wrap', op_sizing='same')
t2 = fxp(5, False, 9, 3, overflow='wrap', op_sizing='same')
t1 - t2
fxp-u9/3(63.0)
如果你检查二进制格式,你会发现减法是正确的:
(t1 - t2).bin(frac_dot=True)
'111111.000'
看 msb 等于
1
,因此当您将此值转换为 signed fxp 时,这将是负值:
# cast from unsigned to signed keeping raw binary value
inter1('0b' + (t1 - t2).bin(frac_dot=True))
fxp-s9/3(-1.0)
现在,
t3 = fxp(48, False, 9, 3, overflow='wrap', op_sizing='same')
t4 = fxp(49, False, 9, 3, overflow='wrap', op_sizing='same')
inter1('0b' + (t3 - t4).bin(frac_dot=True))
fxp-s9/3(-1.0)
最后,让我编写一种更优雅的方法来在代码中使用相同的 fxp 大小:
from fxpmath import Fxp
# Set a template for new Fxp objects
Fxp.template = Fxp(dtype='fxp-u9/3', overflow='wrap', op_sizing='same')
inter1 = Fxp(None, signed=True) # overwrite template's sign
t1 = Fxp(4)
t2 = Fxp(5)
inter1('0b' + (t1 - t2).bin(True)) # or inter1('0b' + (Fxp(4) - Fxp(5)).bin(True))
fxp-s9/3(-1.0)