从整数转换为浮点数如何工作?

How does casting from integers to floating-point numbers work?

假设是32位的值(int32_t,float),它们在内存中的存储方式如下:

// 255
int:   11111111 00000000 00000000 00000000 (big endian)
int:   00000000 00000000 00000000 11111111 (little endian)
float: 0 11111111 000000000000000000000

至此很明显,内存本身的排列方式有所不同,具体取决于解释类型。

进一步假设一个标准的 C 风格转换,这是如何实现的? 我通常使用 x86(_64) 和 ARMHF CPU,但我不熟悉它们各自的汇编语言或 CPU 的内部组织方式,所以如果通过了解这些 CPU 的内部结构就可以相当简单地回答这个问题,请原谅。 主要感兴趣的是 C/++ 和 C# 如何处理此转换。

建议的帖子 Why are floating point numbers inaccurate?Why can't decimal numbers be represented exactly in binary? 有助于理解浮点数学的基本概念,但不要回答这个问题。

如果 int: 11111111 00000000 00000000 00000000 (big endian) 向我们显示内存顺序中的字节(最低地址到最高地址),那么这是小端,而不是大端:255 的最低有效位 11111111 在低位地址,最高有效位 00000000 位于高地址。

float: 0 11111111 000000000000000000000 不是 float 最常用格式中 255 的编码,IEEE-754 binary32。这些位将为 0 10000110 111111100000000000000000(437F000016,或者在存储小端时为 00 00 7F 43)。指数代码134表示指数134−127 = 7,有效位域表示1.11111112 = 1.9921875,所以表示的整个值是+1.9921875•2 7 = 255.

编译器将生成处理值所需的任何指令。通常,具有浮点硬件支持的处理器对于整数和浮点值具有不同的指令,并且通常具有不同的寄存器。要使用 int,编译器将生成将其加载到通用寄存器的指令和对其进行运算的整数算术指令。要使用 float,编译器将生成指令以将其加载到浮点指令和浮点算术指令中以对其进行运算。

如果硬件不支持硬件浮点,编译器会生成指令,以生成正确结果所需的方式解释和处理代表 float 的位。其中大部分是通过调用软件浮点例程库中的例程来完成的。在这些例程中,指令分解浮点表示的各个部分,根据需要进行计算,然后重新组合这些部分以产生浮点结果。

x86_64内置浮点指令,.

ARMHF内置浮点指令; HF 代表硬件浮点或硬浮点。 (我不知道这是官方 ARM 名称的信息;它可能是口语化的。)

当您在 C 中将 int 转换为 float 或反之时,编译器使用内置指令执行转换(除非优化提供了另一种解决方案),如果硬件有这样的指示。硬件指令操纵表示的位来计算结果。如果硬件没有这方面的指令,编译器会生成它需要的任何指令,可能会像上面那样从库中调用例程。

支持大端和小端混合类型的 C 实现很少见。但是,如果支持,编译器将根据需要简单地交换字节。某些硬件可能会通过在加载和存储字时交换字节或在寄存器中交换字节的指令来协助此操作。

Eric解释了细节。但这里有一个来自 x86 架构的特定实例:硬件确实带有一条指令,可以为您执行值的转换。例如,要将双精度浮点数转换为带截断的带符号整数,x86 有指令 CVTTSD2SI。其他转换也类似。硬件执行此操作的方式本质上是找到具有相同值的位模式(当然,处理 overflow/underflow 除外),通常与您在 SW 中执行此操作的方式没有什么不同,当然除外快多了。