功能转换浮到INT(整数巨大)(function to convert float to int (

2019-10-20 21:53发布

这是一所大学的问题。 只是为了确保:-)我们需要实现(浮点)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 << (32 - e);
  /* logical right shift */
  m = (m >> 9) & ~(((0x1 << 31) >> 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));

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

现在,当我做了一些测试运行,这是我的输出(目标是什么它需要,结果是我得到了什么)

:!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必须是无符号湖

int x = 2147483647; 
float f = (float)x;

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

然后升变为-2147483648。

这是怎样发生的? 所以C是做铸件错了吗?

希望有人能帮助我在这里! THX马库斯

编辑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 <<= 1;
    e--;
  };

  /* calculate mantissa */
  int m = (t >> 8) & ~(((0x1 << 31) >> 8 << 1));
  m &= 0x7fffff;

  int res = sign << 31;
  res |= (e << 23);
  res |= m;

  return res;
}

我也想通了,代码工作在范围-2 ^ 24,2 ^ 24的所有整数。 高于/低于有时工作,但大多都没有。

缺少的东西,但我真的不知道。 谁能帮我?

Answer 1:

打印的答案是绝对正确的,因为它是完全依靠数字是铸铁的基本表示。 然而,如果我们理解了数字的二进制表示法,你不会得到这个结果感到惊讶。

要理解的隐式转换与所述赋值运算符(参照C99标准6.5.16)相关联。 C99标准接着说:

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

您的前面的例子示出了由于分配目标类型的范围之外的值未定义的行为。 试图负值分配给一个无符号类型,而不是从浮点转换为整数。

在下面的代码片段断言应该防止发生任何不确定的行为。

#include <limits.h>
#include <math.h>
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和浮动现在是在看相同的内存位的不同方式;

union {
    int    myInt;
    float myFloat;
} my_union;

my_union.myInt = 0x BFFFF2E5;

printf("float is &#37;f\n", my_union.myFloat);

float is -1.999600

你告诉编译器把你拥有的数量(大整数),使之成为一个浮动,而不是解释为浮数。 要做到这一点,你需要告诉编译器来读取以不同的形式从该地址的数量,因此这样的:

myFloat = *(float *)&myInt ;

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

  • &敏 - 在内存中保存您的整数位置。
  • (浮动*) - 真的,我希望编译器使用这个作为一个指针浮动,没有任何编译器认为它可能是。
  • * -从什么是正确的地址读取。
  • myFloat = - 设置这个变量无论是正确的。

所以,你告诉编译器:在(敏)的位置,有一个浮点数,现在把花车到myFloat。



文章来源: function to convert float to int (huge integers)