10

我是 C 编程语言的新手,我想问一个问题。

这里的整数 i 被转换为浮点数,然后 f (不知何故)成功代表 5.0:

int i = 5;
float f = i;   //Something happened here...

但是,如果我们尝试这种方法:

int i = 5;
float f = *(float *)&i;

f 不会得到 5.0,因为它以“浮点方式”解释存储在 i 中的位。那么编译器在第一种情况下实际上做了什么魔法呢?这似乎是一项相当费力的工作......有人可以指定吗?谢谢。

4

7 回答 7

13

这是一项费力的工作,但任何支持浮点的 CPU 都会提供执行此操作的指令。

如果您必须自己将 2 的补码转换int为 IEEE 浮点格式,您将:

  • 取整数 base-2 对数(与最高设置位的索引密切相关),它为您提供指数。对此进行偏移并将其存储在浮点数的指数位中。
  • n将int 的最高位(从第一个设置的非符号位之后的位开始)复制到浮点数的有效位。n然而,a 中有许多有效位float(32 位单精度浮点数为 23)。如果 中有任何剩余位int(即,如果它大于 2 24),并且您有空间的位之后的下一位是1,您可能会或可能不会根据操作中的 IEEE 舍入模式进行舍入。
  • 将符号位从 复制intfloat
于 2012-07-20T15:16:17.953 回答
6

如果你看组装

    int i = 5;
000D139E  mov         dword ptr [i],5  
    float f = i;
000D13A5  fild        dword ptr [i]  
000D13A8  fstp        dword ptr [f]  

fild有什么魔力

于 2012-07-20T15:29:01.330 回答
3

将 int 位转换为浮点数

float IntBitsToFloat(long long int bits)
{
    int sign     = ((bits & 0x80000000) == 0) ? 1 : -1;
    int exponent = ((bits & 0x7f800000) >> 23);
    int mantissa =  (bits & 0x007fffff);

    mantissa |= 0x00800000;
   // Calculate the result:
   float f = (float)(sign * mantissa * Power(2, exponent-150));
   return f;
}
于 2017-05-16T06:37:54.030 回答
2

在 IA32 系统上,编译器将生成以下内容:-

fild dword ptr [i] ; load integer in FPU register, I believe all 32bit integers can be represented exactly in an FPU register
fstp dword ptr [f] ; store fpu register to RAM, truncating/rounding to 32 bits, so the value may not be the same as i
于 2012-07-20T15:30:03.787 回答
1

The magic depends on your platform.

One possibility is that your CPU has a special instruction to copy floating point numbers into integral registers.

Of course someone has to design these CPUs, so this is not really an explanation for the algorithm at hand.

A platform might be using a floating point format that goes like this (actually, this is a fixed-point format for the sake of example):

[sIIIIFFFF]

where s is the sign, the Is are the part before the dot, the Fs are the part after the dot, e.g. (dot is virtual and only for presentation)

 -  47.5000
[sIIII.FFFF]

in this case conversion is almost trivial and can be implemented using bitshifting:

    -47.5000
 >> 4
 ---------------
    -47

And like in this example, commodity C++ implementations use a floating point representation often referred to as IEEE Floating Point, see also IEEE 754-1985. These are more complicated than fixed-point numbers, as they really designate a simple formula of the form _s*mn, however, they have a well defined interpretation and you can unfold them into something more suitable.

于 2012-07-20T15:26:12.663 回答
1

嗯,我刚刚在VC++下编译了有问题的代码,看了下反汇编:

   int i = 5;
00A613BE  mov         dword ptr [i],5 

   float f = i;
00A613C5  fild        dword ptr [i] 
00A613C8  fstp        dword ptr [f] 

第一个汇编语句将 5 移动到由 i 表示的内存中。第二条语句 fild 将 i 表示的内存转换为浮点数,并将其压入 FPU 堆栈。第三条语句 fstp 获取 FPU 堆栈上的内存并将其移至 f。

于 2012-07-20T15:31:11.080 回答
0

In almost all modern systems, the specification for floating point arithmetic is the IEEE754 standard. This details everything from layout in memory to how truncation and rounding is propagated. It's a big area and someting you quite often need to take detailed account of in scientific and engineering programming.

于 2012-07-20T15:26:37.697 回答