C 理解不动点分数部分

C 理解不动点分数部分,c,fixed-point,C,Fixed Point,所以我试着把我的头绕在固定点数字上。到现在为止,一直都还不错。唯一让我困惑的是数字的“分数”部分 我对定点数的理解是,它根据刻度(在本例中等于8位)分割二进制数。左边是整数部分,右边是分数。 XXX.Y其中XXX是整数/整数部分的三个字节,Y是小数部分的一个字节(如果我错了,请纠正我) 让我们看一下以下宏: #define FIX_SCALE 8 #define FIX_FRACTION_MASK ((1 << FIX_SCALE) - 1) #define FIX_WHOLE_MA

所以我试着把我的头绕在固定点数字上。到现在为止,一直都还不错。唯一让我困惑的是数字的“分数”部分

我对定点数的理解是,它根据刻度(在本例中等于8位)分割二进制数。左边是整数部分,右边是分数。
XXX.Y
其中
XXX
是整数/整数部分的三个字节,
Y
是小数部分的一个字节(如果我错了,请纠正我)

让我们看一下以下宏:

#define FIX_SCALE 8
#define FIX_FRACTION_MASK ((1 << FIX_SCALE) - 1)
#define FIX_WHOLE_MASK ~FIX_FRACTION_MASK
#define FIX_FROM_FLOAT(X) ((X) * (1 << FIX_SCALE))
#define FIX_TO_FLOAT(X) ((float)(X) / (1 << FIX_SCALE))
#define FIX_TO_INT(X) ((X) >> FIX_SCALE)
#define FIX_FROM_INT(X) ((X) << FIX_SCALE)
#define FIX_FRACTION(X) ((X) & FIX_FRACTION_MASK)
#define FIX_WHOLE(X) ((X) & FIX_WHOLE_MASK)
生成的整数值是十六进制的
640
0x280
,二进制的
0000 0010 1000 0000

让我们看前两个字节:
0000 0010 1000 0000

我知道
0000 0010
来自哪里,它是整数部分(
2
)。但是我没有得到的是
10000000
,它是小数部分。我只是不明白这和数字5(二进制中的0101)有什么关系。我本以为是
01010000
0000 0101
之类的东西——显然我误解了一个基本概念

如果我写:

int Fraction = FIX_FRACTION(Fixed);
float Fraction = FIX_TO_FLOAT(FIX_FRACTION(Fixed));
我会得到
128
0x80
,十六进制。有意义,因为它掩盖了整数部分,即
2
)。我第一次写这篇文章时,我希望能得到一个
5

如果我写下以下内容,我会得到
0.5

int Fraction = FIX_FRACTION(Fixed);
float Fraction = FIX_TO_FLOAT(FIX_FRACTION(Fixed));
有人能帮我澄清这一困惑吗?为什么分数
0000 1000
中没有任何
101
?为什么我们必须在
FIX\u分数
上执行
FIX\u to\u FLOAT
以获得正确的分数


谢谢。

右边的二进制值。是1/2 1/4 1/8等吗
因此,10.1二进制是2.5,比较十进制和二进制表示中的数字模式不起作用。 让我们暂时忘掉定点数字,看看5和50的二进制表示:

 5: 0000'0101
50: 0011'0010
如您所见,十进制5的二进制模式在十进制50的二进制表示中也找不到

现在要理解为什么十进制0.5在Q23.8二进制中是..00'1000'0000,您需要遵循二进制到十进制的转换规则:

将每个1替换为2^位置,并将数字相加

position:      7 6 5 4  3 2 1 0  -1-2-3-4 -5-6-7-8
binary number: 0 0 0 0  0 0 1 0 . 1 0 0 0  0 0 0 0

2^1+2^-1=2+0.5=2.5

整数表示10的不同幂:

()

So 10203=1×10000+0×1000+2×100+0×10+3×1

小数延续了这个模式,代表10的负幂:

所以0.10203=1/10+0/100+2/1000+0/10000+3/100000

十进制数2.5在2s列中有一个“2”,在1/10列中有一个“5”,因此总数为2×1+5/10

二进制不动点的工作方式完全相同,除了幂为2而不是10。整数部分是1s列、2s列、4s列、8s列等,小数部分是1/2s列、1/4th列、1/8th列等

例如,如果数字是4.4格式,其中第一个半字节是无符号整数部分,第二个半字节是小数部分,对于二进制数10101001,整数部分表示

1×8+0×4+1×2+0×1

小数部分代表

1/2+0/4+0/8+1/16

所以十进制等价物是

1×8+0×4+1×2+0×1+1/2+0/4+0/8+1/16

=10.5625

签名版本与此类似:

()

因此,在二进制格式中,2.5是
0b0000 0010 1000 0000
,第一个字节在2s列中有1,在1s列中有0,因此


…+0×4+1×2+0×1+1/2+0/4+0/8+…

在我的答案上展开——二进制是一种数字系统,而不是编码。这是基数2而不是基数10。5d是1/2是0.1b我不知道你说的“.5d是1/2是0.1b”是什么意思?你能再详细说明一下吗?对不起,说得太慢了。二进制数在小数点两侧都有二进制权重(指数)。1/2在二进制中等于0.1,因为第一个小数位的值是1/2。在十进制数学中,小数点右侧的值为1/10。1/2=5/10=0.5十进制