IEEE – 754 – 找到signbit,exponent,frac,normalized等
我接收一个8位hex数作为IEEE 754位浮点数,我想打印有关该数字的信息(signbit,expbits,fractbits,normalized,denormalized,infinity,zero,NAN)浮点应该是单个。
我读了一下比特移位,我想这就是我想这样做的原因吗? 但是,我不是百分百肯定。 我知道符号位位于数字的最左侧位置。 表示正面或负面。 我将它移动多少才能找到每个? 我只是继续转移它找到每一个? 谁能解释我是如何找到每一个人的?
我会换1来找到标志吗? 我会换8来得到指数吗? 我会换23来获得压裂吗?
signbit应为零
expbits应该是128
fracbits应该是0x00000000我认为……
如果是这样我怎么在换class后测试呢?
这就是我到目前为止所拥有的
#include #include int main(int argc, char *argv[]) { short wordOrder = 0x0100; int HexNumber; printf("Hex IEEE - 754\n"); if(wordOrder == 0x0100) { printf("\nbyte order: big-endian\n"); } else { printf("byte order: little-endian\n"); } printf("\n>"); scanf("%x", &HexNumber); printf("\n%#x",HexNumber); return 0; }
我的输入(scanf)我想要的方式..
>40000000 0x40000000
它正在做什么..
对于单精度数,高位是符号,接下来的8位是指数,剩下的23位是尾数。 所以…
bool negative = !!(HexNumber & 0x80000000); int exponent = (HexNumber & 0x7f800000) >> 23; int mantissa = (HexNumber & 0x007FFFFF);
如果指数为255,则数字为+ – 无穷大或NaN,具体取决于尾数是否为零(0表示无穷大)。 如果指数为零,则以太数字为+ – 零(如果尾数为零)或者尾数是实际的非标准化小数值。
如果指数是其他任何东西,则在分数的顶部有一个隐藏的位,使其为24位。 在这种情况下,可以通过从指数中减去127来计算实际指数,使得它在-127到+127的范围内,两个指数的幂。
要检查您的代码是否正确,请参阅转换器小程序http://www.h-schmidt.net/FloatApplet/IEEE754.html
我发现Applet对于检查一些值非常有用。
&在两个值之间进行逐位操作。 如果其中一个值是常量并具有一些有用的属性。
A | B | A & B ---+---+------- 0 | 0 | 0 0 | 1 | 0 ---+---+------- 1 | 0 | 0 1 | 1 | 1
正如您在真值表中看到的那样,前两行显示如果A = 0,则A和B = 0.因此,在某个位置将掩码置于零中具有清除该位的效果。
最后两行显示如果A = 1,A&B = B.因此,在某个位置将掩码放在掩码中具有传递该位的效果。
因此,您可以使用常量掩码清除已知字段之外的位。
您可以使用OR(|)和XOR(^)执行相同的练习,并得出与|一起使用的蒙版 具有设置掩码为1的值的位的效果。^具有切换掩码为1的值的位的效果。
/ *回应评论* /
它不是一个指数位,它是一个8位长的指数字段。 所以,如果你按如下方式构建你的面具:
0111 1111 1000 0000 0000 0000 0000 0000 (mask === 0x7F800000) 1011 1010 0101 0110 0110 1010 1001 1010 (value) ------------------------------------------------- 0011 1010 0000 0000 0000 0000 0000 0000 (result)
您可以在此处看到,此操作遗留的所有内容都是组成指数字段的位(即01110100)。 现在,如果您想知道该字段的值,则需要将结果向右移动所需的数量。 所需的量(通常)是字段的最低有效位的零索引位位置。 对于指数字段,所需的移位量为23。
另一方面,向右移动时必须小心。 我们可以在这里使用它,因为我们知道我们的掩码在最重要的位中有一个零,但如果不是这种情况,我们最好将结果转换为无符号值,然后再向右移动。 如果你不这样做,你会得到签名扩展。
int8_t exponent = ((uint32_t) (value & 0x7F800000)) >> 23; // the cast is not necessary in this case because the mask has a 0 in the msb
如果你想提取符号位,这个演员阵容将变得很重要:
int8_t sign = ((uint32_t) (value & 0x80000000)) >> 31;
(我不知道你在哪里得到你必须换8来提取符号位的概念)
除了你已经考虑过的一点点,你可以使用一些库函数来解析和缩放浮点数。
如果你有一个float
或double
,你可以使用std::frexp()
来确定它的有效数(或尾数)和指数。 指数将是整数,但有效数将是0.5和1之间的实数或零。
冰冻问道:
有人能解释一下这里发生了什么吗? 我们在哪里提出&号码?
&运算符是按位AND运算符。 hex数字是位掩码,通过使用适当的掩码应用&运算符,您可以隔离您感兴趣的位。
@vicatcu,或其他任何人
icelated ..
IEEE单精度浮点标准表示需要32位字,其可以表示为从0到31编号,从左到右。 第一位是符号位,后8位是指数位,最后23位是分数。
因此,为了提取符号位,我们使用适当的掩码并移动31以获得最后的符号? 除了获得指数的值。 因为它的长度为8位 – 我们将31 – 8(23)移位到最后? 如果为真,那么尾数不需要移位? 另外,要提取值,我们使用掩码。 这部分让我很困惑。 我认为面具是hex等效的。 我们如何提出这个hex数? ex:int exponent =(HexNumber&0x7f800000)谢谢 – 我想我得到了这个….
代码修订:
#include #include int main(int argc, char *argv[]) { int HexNumber; int a = 0x12345678; unsigned char *c = (unsigned char*)(&a); if (*c == 0x78) { printf("\nlittle-endian\n"); } else { printf("\nbig-endian\n"); } printf("\n>"); scanf("%x", &HexNumber); printf("\n%#x",HexNumber); bool negative = !!(HexNumber & 0x80000000); int exponent = (HexNumber & 0x7f800000) >> 23; int mantissa = (HexNumber & 0x007FFFFF); printf("\nsignBit %d,", negative); printf("expbits %d,", exponent); printf("fractbits %#x,", mantissa); return 0; }