了解定点小数部分

时间:2016-04-16 04:39:38

标签: c fixed-point

所以我试图绕过定点数字。到现在为止还挺好。让我困惑的唯一一件事是数字的“分数”部分。

我对定点数的理解是它根据比例(在这种情况下等于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)

考虑以下示例:

int Fixed = FIX_FROM_FLOAT(2.5f);

结果整数值为6400x280为十六进制,0000 0000 0000 0000 0000 0010 1000 0000为二进制。

我们先取两个字节:0000 0010 1000 0000

我理解0000 0010的来源,它是整数部分(2)。但我得不到的是1000 0000这是小数部分。我只是看不出它与数字5的关系(二进制为0101)。我本来期望像0101 00000000 0101这样的东西 - 显然我在这里误解了一个基本概念。

如果我写:

int Fraction = FIX_FRACTION(Fixed);

我会得到1280x80十六进制。这是有道理的,因为它掩盖了整数部分2)。我第一次写这篇文章的时候,我希望得到一个5

如果我写的话,我会得到0.5

float Fraction = FIX_TO_FLOAT(FIX_FRACTION(Fixed));

有人可以为我清除这种困惑吗?为什么分数0000 1000中没有101?为什么我们必须FIX_TO_FLOAT FIX_FRACTION来获得正确的分数?

感谢。

3 个答案:

答案 0 :(得分:1)

整数代表10的不同幂:

Integer columns decimal representationsource

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

小数点继续这种模式,代表10的负幂:

Fractional columns decimal representation

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

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

二进制不动点的工作原理完全相同,不同之处在于2的幂而不是10。整数部分是1s列,2s列,4s列,8s列等,小数部分是1 / 2s列,1 / 4th列,1 / 8th列等。

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

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

签名版本相似:

signed binary 4.4 representationsource

因此,在您的二进制格式中,其中2.5是0b0000 0010 1000 0000,第一个字节在2s列中为1,在1s列中为0,所以它是

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

答案 1 :(得分:0)

比较十进制和二进制表示中的数字模式不起作用。 让我们暂时忘记定点数,看看5和50的二进制表示:

 5: 0000'0101
50: 0011'0010

如您所见,小数5的二进制模式也无法在十进制50的二进制表示中找到。

现在要理解为什么十进制0.5在Q23.8二进制中是..00&#39; 1000&00; 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

答案 2 :(得分:-1)

右边的二进制值。是1/2 1/4 1/8等 因此10.1二进制是2.5