c - 如何将 IEEE 754 单精度二进制 float 转换为十进制数?

标签 c binary ieee-754

I am working on a program that needs to convert a 32-bit number into a decimal number.

我从输入中获得的数字是一个表示为 float 的 32 位数字。第一位是符号,接下来的 8 位是指数,另外 23 位是尾数。我正在用 C 编写程序。在输入中,我将那个数字作为 char[] 数组获取,然后我创建了一个新的 int[] 数组,我在其中存储符号、指数和尾数。但是,当我尝试将尾数存储在某种数据类型中时,尾数有问题,因为我需要将尾数用作数字,而不是数组:formula=sign*(1+0.mantissa)* 2^(exponent-127).

这是我用来存储尾数的代码,但程序仍然给我错误的结果:

double oMantissa=0;
int counter=0;
for(counter=0;counter<23;counter++)
{
    if(mantissa[counter]==1)
    {
        oMantissa+=mantissa[counter]*pow(10,-counter);
    }
}

mantissa[] 是一个 int 数组,我已经从 char 数组转换了尾数。当我从 formula 得到值时,它必须是二进制数,我必须将它转换为十进制,所以我将得到数字的值。你能帮我存储尾数的 23 位吗?而且,我不能使用像 strtoul 这样的函数将 32 位数字直接转换为二进制。我必须使用公式

最佳答案

在给出所有公式和样本编号以及计算器的情况下,以下代码的哪一部分难以正确?

#include <stdio.h>
#include <limits.h>

#if UINT_MAX >= 0xFFFFFFFF
typedef unsigned uint32;
#else
typedef unsigned long uint32;
#endif

#define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]

// Ensure uint32 is exactly 32-bit
C_ASSERT(sizeof(uint32) * CHAR_BIT == 32);

// Ensure float has the same number of bits as uint32, 32
C_ASSERT(sizeof(uint32) == sizeof(float));

double Ieee754SingleDigits2DoubleCheat(const char s[32])
{
  uint32 v;
  float f;
  unsigned i;
  char *p1 = (char*)&v, *p2 = (char*)&f;

  // Collect binary digits into an integer variable
  v = 0;
  for (i = 0; i < 32; i++)
    v = (v << 1) + (s[i] - '0');

  // Copy the bits from the integer variable to a float variable
  for (i = 0; i < sizeof(f); i++)
    *p2++ = *p1++;

  return f;
}

double Ieee754SingleDigits2DoubleNoCheat(const char s[32])
{
  double f;
  int sign, exp;
  uint32 mant;
  int i;

  // Do you really need strto*() here?
  sign = s[0] - '0';

  // Do you really need strto*() or pow() here?
  exp = 0;
  for (i = 1; i <= 8; i++)
    exp = exp * 2 + (s[i] - '0');

  // Remove the exponent bias
  exp -= 127;

  // Should really check for +/-Infinity and NaNs here

  if (exp > -127)
  {
    // Normal(ized) numbers
    mant = 1; // The implicit "1."
    // Account for "1." being in bit position 23 instead of bit position 0
    exp -= 23;
  }
  else
  {
    // Subnormal numbers
    mant = 0; // No implicit "1."
    exp = -126; // See your IEEE-54 formulas
    // Account for ".1" being in bit position 22 instead of bit position -1
    exp -= 23;
  }

  // Or do you really need strto*() or pow() here?
  for (i = 9; i <= 31; i++)
    mant = mant * 2 + (s[i] - '0');

  f = mant;

  // Do you really need pow() here?
  while (exp > 0)
    f *= 2, exp--;

  // Or here?
  while (exp < 0)
    f /= 2, exp++;

  if (sign)
    f = -f;

  return f;
}

int main(void)
{
  printf("%+g\n", Ieee754SingleDigits2DoubleCheat("110000101100010010000000000000000"));
  printf("%+g\n", Ieee754SingleDigits2DoubleNoCheat("010000101100010010000000000000000"));
  printf("%+g\n", Ieee754SingleDigits2DoubleCheat("000000000100000000000000000000000"));
  printf("%+g\n", Ieee754SingleDigits2DoubleNoCheat("100000000100000000000000000000000"));
  printf("%+g\n", Ieee754SingleDigits2DoubleCheat("000000000000000000000000000000000"));
  printf("%+g\n", Ieee754SingleDigits2DoubleNoCheat("000000000000000000000000000000000"));
  return 0;
}

输出(ideone):

-98.25
+98.25
+5.87747e-39
-5.87747e-39
+0
+0

关于c - 如何将 IEEE 754 单精度二进制 float 转换为十进制数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16164620/

相关文章:

c -/**/评论比//更受欢迎吗?

c - 理解反汇编——看两个 main() 的

java - Java 中使用二进制 I/O 分割和连接回文件的机制

阶乘的精度运算和溢出

algorithm - 自定义函数无法将小数转换为单精度 float

隐藏赋值的 C 宏技巧?

c - 错误: ‘struct msghdr’ has no member named ‘msg_iov’

python - 循环遍历没有扩展名的二进制文件

c - 十进制到二进制转换器 : add spaces to output

floating-point - IEEE int->float 转换是否与 + 和 * 交换?