题
改装一次要多少钱 float
到一个 double
?它像一个微不足道的 int
到 long
转换?
编辑:我假设一个平台,其中 float 为 4 字节,double 为 8 字节
解决方案
平台注意事项
这取决于用于浮点计算的平台。对于 x87 FPU,转换是免费的,因为寄存器内容是相同的 - 有时您可能付出的唯一代价是内存流量,但在许多情况下甚至没有流量,因为您可以简单地使用该值而不进行任何转换。x87 在这方面实际上是一个奇怪的野兽 - 很难正确区分浮点型和双精度型,因为使用的指令和寄存器是相同的,不同的是加载/存储指令和计算精度本身是使用状态位控制的。使用混合浮点/双精度计算可能会导致意外结果(因此有编译器命令行选项来控制确切的行为和优化策略)。
当您使用 SSE 时(有时 Visual Studio 默认使用 SSE),情况可能会有所不同,因为您可能需要传输 FPU 寄存器中的值或执行某些显式操作来执行转换。
内存节省性能
作为总结,并回答您在其他地方的评论:如果要将浮点计算的结果存储到 32b 存储中,结果将具有相同的速度或更快,因为:
- 如果您在 x87 上执行此操作,则转换是免费的 - 唯一的区别是将使用 fstp dword[] 而不是 fstp qword[]。
- 如果在启用 SSE 的情况下执行此操作,您甚至可能会看到一些性能提升,因为一旦计算精度仅为浮点而不是默认的双精度,就可以使用 SSE 完成一些浮点计算。
- 在所有情况下,内存流量都较低
其他提示
在某些平台上浮动到双重转换是免费的(PPC,x86,如果你的编译器/运行时使用了“告诉我使用什么类型的地狱”,我将以长双重评估所有内容,nyah nyah“评估模式”。
在使用SSE寄存器在指定类型中实际进行浮点计算的x86环境中,float和double之间的转换与浮点加法或乘法一样昂贵(即,不太可能是性能考虑因素,除非你正在做很多)。
在缺乏硬件浮点的嵌入式环境中,它们可能有点昂贵。
这特定于您正在使用的C ++实现。在C ++中,默认浮点类型是 double 。编译器应该为以下代码发出警告:
float a = 3.45;
因为双值3.45被分配给浮点数。如果您需要专门使用浮点数,请使用 f :
后缀该值float a = 3.45f;
关键是,所有浮点数默认为 double 。如果您不确定编译器的实现细节并且不了解浮点计算,那么坚持这个默认值是安全的。避免演员。
另见 C ++编程语言第4.5节。
我无法想象它会变得更加复杂。将int转换为long并将float转换为double的最大区别在于int类型有两个组件(符号和值),而浮点数有三个组件(符号,尾数和指数)。
编码IEEE 754单精度 在32位中使用1位作为符号,8 指数的位,以及23位 有意义的。但是,它使用了 隐藏位,所以有效数是24 位(p = 24),即使它是 仅使用23位编码。
- David Goldberg,每个计算机科学家应该了解浮点数算术
因此,在float和double之间进行转换将保持相同的符号位,将float的尾数的最后23/24位设置为double的尾数,并将float的指数的最后8位设置为double的指数。
IEEE 754 甚至可以保证这种行为......我还没有检查了一下,所以我不确定。
可能比将int转换为long要慢一些,因为所需的内存更大,操作更复杂。关于内存对齐问题的一个很好的参考资料
也许这有帮助:
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
double _ftod(float fValue)
{
char czDummy[30];
printf(czDummy,"%9.5f",fValue);
double dValue = strtod(czDummy,NULL);
return dValue;
}
int main(int argc, char* argv[])
{
float fValue(250.84f);
double dValue = _ftod(fValue);//good conversion
double dValue2 = fValue;//wrong conversion
printf("%f\n",dValue);//250.840000
printf("%f\n",dValue2);//250.839996
getch();
return 0;
}