2

我将一个 8 位十六进制数作为 IEEE 754 位浮点数,我想打印有关该数字的信息(符号位、expbits、fractbits、规范化、非规范化、无穷大、零、NAN)浮点应该是一个。

我阅读了位移位,我认为这就是我应该这样做的方式?但是,我不是 100% 确定。我知道符号位位于数字的最左侧。这表示正面或负面。我要转移多少才能找到每个?我只是不断移动它来找到每一个吗?有人可以解释我如何找到每一个吗?

我会移动 1 以找到符号位吗?我会移动 8 以获得指数吗?我会移动 23 来获得压裂吗?

符号位应为零

expbits 应该是 128

我认为 fracbits 应该是 0x00000000...

如果是这样,我转移后如何测试它?

这就是我到目前为止所拥有的

#include <stdio.h>
#include <stdlib.h>

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

这就是它在做什么..

4

7 回答 7

13

对于单精度数,高位是符号,接下来的 8 位是指数,其余 23 位是尾数。所以...

bool negative = !!(HexNumber & 0x80000000);
int exponent = (HexNumber & 0x7f800000) >> 23;
int mantissa = (HexNumber & 0x007FFFFF);

如果指数为 255,则数字为 +- 无穷大或 NaN,具体取决于尾数是否为零(0 表示无穷大)。如果指数为零,则该数字为 +- 零(如果尾数为零)或尾数是实际的未归一化小数值。

如果指数是其他值,则在分数的顶部有一个隐藏的位,使其成为 24 位。在这种情况下,可以通过从指数中减去 127 来计算实际指数,使其在 -127 到 +127 的范围内,即两个指数的幂。

于 2010-01-11T21:39:56.557 回答
1

要检查您的代码是否正确,请使用转换器小程序 http://www.h-schmidt.net/FloatApplet/IEEE754.html

我发现 Applet 对检查某些值很有用。

于 2010-01-11T21:56:53.993 回答
1

除了您已经在考虑的小玩意之外,还有一些库函数可以让您剖析和缩放浮点数。

如果你手上有一个floatdouble,你可以用std::frexp()它来确定它的有效数(或尾数)和指数。指数是整数,但有效数字是介于 0.5 和 1 之间的实数或零。

于 2010-01-11T22:12:24.060 回答
1

& 在两个值之间进行逐位运算。如果其中一个值是常数并且具有一些有用的属性。

  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。因此,在掩码中的某个位置放置一个 1 具有传递该位的效果。

因此,您可以使用常量掩码来清除已知字段之外的位。

您可以使用 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 才能提取符号位的概念)

于 2010-01-12T20:11:34.113 回答
0

icelated 问:

有人可以解释这里发生了什么吗?我们在哪里提出 & 数字?

& 运算符是按位与运算符。十六进制数字是位掩码,通过应用带有适当掩码的 & 运算符,您可以隔离您感兴趣的位。

于 2010-01-12T00:45:12.360 回答
0

@vicatcu,或其他任何人

冰镇..

IEEE 单精度浮点标准表示需要一个 32 位字,它可以表示为从左到右从 0 到 31 的编号。第一位是符号位,接下来的八位是指数位,最后 23 位是小数。

因此,为了提取符号位,我们使用适当的掩码并移位 31 以得到最后的符号?除了得到指数的值。因为,它的长度为 8 位 - 我们移动 31 - 8(23) 以将其移动到末尾?如果为真,那么尾数不需要移位?此外,为了提取我们使用掩码的值。这部分让我感到困惑。我认为掩码是十六进制等效值。我们如何得出这个十六进制数?例如:int exponent = (HexNumber & 0x7f800000) 谢谢 - 我想我明白了....

于 2010-01-12T23:42:08.100 回答
0

代码修改:

#include <stdio.h>
 #include <stdlib.h>

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;
}
于 2010-01-19T04:07:26.877 回答