在C中将float转换为int(按位)

给定代表IEEE 754浮点数的32位,如何使用表示上的整数或位操作(而不是使用机器指令或编译器操作进行转换)将数字转换为整数?

编辑#1:

我必须遵循function但在某些情况下失败:

输入:int x(包含IEEE 754格式的32位单精度数)

if(x == 0) return x; unsigned int signBit = 0; unsigned int absX = (unsigned int)x; if (x < 0) { signBit = 0x80000000u; absX = (unsigned int)-x; } unsigned int exponent = 158; while ((absX & 0x80000000) == 0) { exponent--; absX <> 8; unsigned int result = signBit | (exponent << 23) | (mantissa & 0x7fffff); printf("\nfor x: %x, result: %x",x,result); return result; 

编辑#2:

还需要帮助: https : //cs.stackexchange.com/questions/3484/converting-function-to-bitwise-only

C有“联合”来处理这种类型的数据视图:

 typedef union { int i; float f; } u; u u1; u1.f = 45.6789; /* now u1.i refers to the int version of the float */ printf("%d",u1.i); 

(有人应该仔细检查这个答案,特别是边界情况和负值的四舍五入。另外,我把它写成舍入到最接近。要重现C的转换,这应该改为舍入为零。)

从本质上讲,这个过程是:

将32位分成一个符号位,八个指数位( e )和23个有效位( f )。 我们将这些视为二进制补码整数。

如果e为255,则浮点对象为无穷大(如果f为零)或NaN(否则为)。 在这种情况下,无法执行转换,应报告错误。

否则,如果e不为零,则向f添加2 24 。 (如果e不为零,则有效数字在其前面隐含有1位。添加2 24会使该位在f中显式。)

e减去127。 (这将指数从其偏置/编码forms转换为实际指数。如果我们正在进行任何值的一般转换,我们将不得不处理e为零时的特殊情况:减去126而不是127.但是,因为我们只转换为整数结果,我们可以忽略这种情况,只要这些微小输入数的整数结果为零。)

如果s为0(符号为正)且e为31或更大,则该值溢出带符号的32位整数(它为2 31或更大)。 无法执行转换,应报告错误。

如果s为1(符号为负)且e大于31,则该值溢出带符号的32位整数(小于或等于-2 32 )。 如果s为1, e为32,并且f大于2 24 (设置了任何原始有效位数),则该值溢出有符号的32位整数(小于-2 31 ;如果原始f为零,它恰好是-2 31 ,不会溢出)。 在任何这些情况下,都无法执行转换,应报告错误。

现在我们有一个s ,一个e和一个不会溢出的值的f ,所以我们可以准备最终值。

如果s为1,则将f设置为-f

指数值用于1(包括)和2(不包括)之间的有效数字,但是我们的有效数字从2 24开始 。 所以我们必须对此进行调整。 如果e是24,我们的有效数字是正确的,我们就完成了,所以返回f作为结果。 如果e大于24或小于24,我们必须适当地改变有效数。 此外,如果我们要向右移动f ,我们可能需要对其进行舍入,以将结果四舍五入到最接近的整数。

如果e大于24,则向左移动e -24位。 结果返回f

如果e小于-1,则浮点数介于-½和½之间,不包括。 结果返回0。

否则,我们将向右移24位。 但是,我们将首先保存舍入所需的位数。 将r设置为将f转换为无符号32位整数并将其向左移位32-(24- e )位(相当于左移8 + e位)的结果。 这将取出将从f (下方)移出的位,并在32位中“左移”调整它们,因此我们在它们开始时有一个固定的位置。

向右移24位。

如果r小于2 31 ,则不执行任何操作(这是向下舍入;移位截断位)。 如果r大于2 31 ,则在f中加1(这是向上舍入)。 如果r等于2 31 ,则将f的低位加到f 。 (如果f为奇数,则向f中加1。在两个相等的近似值中,这将舍入到偶数值。)返回f

&x给出了&x的地址,因此具有float*类型。

(int*)&x将指针转换为指向int的指针,即转换为int*东西。

*(int*)&x取消引用指针到int值。 在intfloat具有不同大小的机器上,它不会做你所相信的。

并且可能存在字节序问题。

该解决方案用于快速平方根算法。

您不能(有意义地)以这种方式将浮点数转换为’整数’( signed intint )。

它可能最终具有整数类型,但它实际上只是IEEE754编码空间的索引,本身并不是一个有意义的值。

您可能会认为unsigned int作为位模式和整数值具有双重目的,但int不会。


还存在对已签名的int进行位操作的平台问题 。

 float x = 43.133; int y; assert (sizeof x == sizeof y); memcpy (&y, &x, sizeof x); ... 

您可以使用引用强制转换浮点数。 像这样的演员阵容永远不应该生成任何代码。

C ++

 float f = 1.0f; int i = (int &)f; printf("Float %f is 0x%08x\n", f, i); 

输出:

 Float 1.000000 is 0x3f800000 

如果你想要c ++样式转换使用reinterpret_cast,就像这样。

 int i = reinterpret_cast(f); 

它不适用于表达式,您必须将其存储在变量中。

  int i_times_two; float f_times_two = f * 2.0f; i_times_two = (int &)f_times_two; i_times_two = (int &)(f * 2.0f); main.cpp:25:13: error: C-style cast from rvalue to reference type 'int &'