将float转换为int(大整数)的函数

这是一个大学问题。 只是为了确保:-)我们需要实现(浮动)x

我有以下代码必须将整数x转换为存储在无符号整数中的浮点二进制表示。

unsigned float_i2f(int x) { if (!x) return x; /* get sign of x */ int sign = (x>>31) & 0x1; /* absolute value of x */ int a = sign ? ~x + 1 : x; /* calculate exponent */ int e = 0; int t = a; while(t != 1) { /* divide by two until t is 0*/ t >>= 1; e++; }; /* calculate mantissa */ int m = a <> 9) & ~(((0x1 <> 9 << 1)); /* add bias for 32bit float */ e += 127; int res = sign << 31; res |= (e << 23); res |= m; /* lots of printf */ return res; } 

我现在遇到的一个问题是,当我的整数太大时,我的代码就会失败。 我实施了这个控制程序:

 float f = (float)x; unsigned int r; memcpy(&r, &f, sizeof(unsigned int)); 

这当然总能产生正确的输出。

现在当我做一些测试运行时,这是我的输出(GOAL是它需要的,结果是我得到的)

 :!make && ./btest -f float_i2f -1 0x80004999 make: Nothing to be done for `all'. Score Rating Errors Function x: [-2147464807] 10000000000000000100100110011001 sign: 1 expone: 01001110100000000000000000000000 mantis: 00000000011111111111111101101100 result: 11001110111111111111111101101100 GOAL: 11001110111111111111111101101101 

所以在这种情况下,添加1作为LSB。

下一个案例:

 :!make && ./btest -f float_i2f -1 0x80000001 make: Nothing to be done for `all'. Score Rating Errors Function x: [-2147483647] 10000000000000000000000000000001 sign: 1 expone: 01001110100000000000000000000000 mantis: 00000000011111111111111111111111 result: 11001110111111111111111111111111 GOAL: 11001111000000000000000000000000 

这里1加到指数中,而尾数是它的补码。

我试过几个小时在互联网上查看ip以及我的书等,但我找不到任何对这个问题的引用。 我猜这与尾数只有23位的事实有关。 但是我该如何处理呢?

编辑:这一部分已经过时了,感谢下面的评论。 int l必须是unsigned l。

 int x = 2147483647; float f = (float)x; int l = f; printf("l: %d\n", l); 

然后我变成-2147483648。

怎么会发生这种情况? 所以C做错了吗?

希望有人可以帮助我! Thx Markus

编辑2:

我的更新代码现在是这样的:

 unsigned float_i2f(int x) { if (x == 0) return 0; /* get sign of x */ int sign = (x>>31) & 0x1; /* absolute value of x */ int a = sign ? ~x + 1 : x; /* calculate exponent */ int e = 158; int t = a; while (!(t >> 31) & 0x1) { t <> 8) & ~(((0x1 <> 8 << 1)); m &= 0x7fffff; int res = sign << 31; res |= (e << 23); res |= m; return res; } 

我还发现代码适用于-2 ^ 24,2 ^ 24范围内的所有整数。 上面/下面的所有东西有时都可以,但大部分都不行

有些东西不见了,但我真的不知道是什么。 谁能帮我?

打印的答案绝对正确,因为它完全取决于正在投射的数字的基本表示。 但是,如果我们理解数字的二进制表示,您将不会对此结果感到惊讶。

要理解隐式转换与赋值运算符相关(参考C99标准6.5.16)。 C99标准继续说:

6.3.1.4实数浮点数和整数当实数浮点类型的有限值转换为_Bool以外的整数类型时,小数部分被丢弃(即,该值被截断为零)。 如果整数部分的值不能用整数类型表示,则行为是未定义的。

您之前的示例说明了由于分配了目标类型范围之外的值而导致的未定义行为。 尝试将负值分配给无符号类型,而不是将浮点数转换为整数。

以下代码段中的断言应该防止发生任何未定义的行为。

 #include  #include  unsigned int convertFloatingPoint(double v) { double d; assert(isfinite(v)); d = trunc(v); assert((d>=0.0) && (d<=(double)UINT_MAX)); return (unsigned int)d; } 

另一种做同样事情的方法,创建一个包含32位整数和浮点数的联合。 int和float现在只是查看同一位内存的不同方式;

 union { int myInt; float myFloat; } my_union; my_union.myInt = 0x BFFFF2E5; printf("float is %f\n", my_union.myFloat); float is -1.999600 

你告诉编译器取你拥有的数字(大整数)并使它成为一个浮点数,而不是解释数字AS浮点数。 为此,您需要告诉编译器以不同的forms从该地址读取数字,因此:

 myFloat = *(float *)&myInt ; 

这意味着,如果我们把它分开,从右边开始:

  • &myInt - 内存中保存整数的位置。
  • (float *) - 实际上,我希望编译器使用它作为float的指针,而不是编译器认为它可能是什么。
  • * -从右边的地址读取。
  • myFloat = - 将此变量设置为右侧的任何值。

所以,你告诉编译器:在(myInt)的位置,有一个浮点数,现在将浮点数放入myFloat。