这个浮点到十进制转换的错误是什么?

时间:2018-04-17 15:20:35

标签: floating-point

0 10000101 01010011000000000000001转换为十进制(84.75000762939453125)效果很好:

FP: 0 10000101 01010011000000000000001
Fraction: (1.)01010011000000000000001
Exp 10000101: 133
Bias: 133-127=6
Moving by exp: 1010100.11000000000000001
Convert parts to decimal: 84.75000762939453125

为什么我无法将0 00000001 00000000000000000000001转换为十进制(即1.1754945E-38):

FP: 0 00000001 00000000000000000000001
Fraction: (1.)00000000000000000000001
Exp 00000001: 1
Bias: 1-127=-126
Moving by exp: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
Convert parts to decimal: 0.?!?!?!

无法1.1754945E-38将二进制0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001转换为十进制。

我哪里错了?

2 个答案:

答案 0 :(得分:2)

  

我哪里错了?

一些问题

Moving by exp不正确

0应该是1

FP: 0 00000001 00000000000000000000001
Fraction: (1.)00000000000000000000001
Exp 00000001: 1
Bias: 1-127=-126
// wrong
Moving by exp: 0.0000000000 (many zeros omitted) 0000000000000000000000000001
// should be 
Moving by exp: 0.0000000000 (many zeros omitted) 0000100000000000000000000001
//                                                   ^

网站不正确

对于高达0.0000000000000000000000000000000000000000000000000000000000000000000001 2

的值,OP reference tool返回0

输入0.0000000000 (many zeros omitted) 0000100000000000000000000001也会报告0。

正确转换字符串" 0.0000000000(省略多个零)0000100000000000000000000001"作为基数2分数容易给出OP的预期值。

#include <math.h>
#include <stdio.h>

int main(void) {
  char *Moving_by_exp = "0."
      "0000000000"
      "0000000000"
      "0000000000"
      "0000000000"
      "0000000000"
      "0000000000"
      "0000000000"
      "0000000000"
      "0000000000"
      "0000000000"
      "0000000000"
      "0000000000"
      "00000100000000000000000000001";
  char *s = Moving_by_exp;
  double x = 0.0;
  int power2 = 0;
  while (*s) {
    power2--;
    if (*s == '.') power2 = 0;
    else x = x*2 + *s - '0';
    s++;
  }
  printf("%.7e\n", x*pow(2,power2));
  printf("%.16e\n", x*pow(2,power2));
}

输出继电器

1.1754945e-38
1.1754944909521339e-38

OP不正确&#34; 0.0000000000(省略多个零)0000000000000000000000000001&#34;转换为1.4012985e-45

答案 1 :(得分:0)

你没错。该工具是错误的。

我找到了一个页面(第一个是我用Google搜索时出现的#34; ieee 754转换器&#34;),这个页面没有问题:https://www.h-schmidt.net/FloatConverter/IEEE754.html

我写了一个小C程序,它可能包含一些不可移植性,未定义的行为和过时的编码实践,但它显示了一些相关的浮点数和整数之间的转换:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef union {
  float f;
  int i;
} both;

void printbits(int k) {
  int i;
  for (i = 0; i < 32; i++) {
    if (i == 1 || i == 9)
      printf(" ");
    if (k & (1<<(31-i)))
      printf("1");
    else
      printf("0");
  }
  printf("\n");
}

int main() {

  printf("sizeof(float) = %ld\n", sizeof(float));
  printf("sizeof(int) = %ld\n", sizeof(int));

  both u;

  u.i = 0x00800001;
  printbits(u.i);
  printf("%g\n", u.f);
  printf("%d %d\n", fpclassify(u.f), isnormal(u.f));
  printf("\n");

  u.i = 0x00800000;
  printbits(u.i);
  printf("%g\n", u.f);
  printf("%d %d\n", fpclassify(u.f), isnormal(u.f));
  printf("\n");

  u.i = 0x007fffe1;
  printf("%g\n", u.f);
  printf("%d %d\n", fpclassify(u.f), isnormal(u.f));
  printf("\n");

  u.i = 0x42a98001;
  printf("%g\n", u.f);
  printf("%g\n", 84.75000762939453125);
  printf("%d %d\n", fpclassify(u.f), isnormal(u.f));
  printf("\n");

  u.f = 1.17549e-38;
  printbits(u.i);
  printf("%#010x\n", u.i);
  printf("%d %d\n", fpclassify(u.f), isnormal(u.f));

  u.f = 1.1754944e-38;
  printbits(u.i);
  printf("%#010x\n", u.i);
  printf("%d %d\n", fpclassify(u.f), isnormal(u.f));

  u.f = 1.1754945e-38;
  printbits(u.i);
  printf("%#010x\n", u.i);
  printf("%d %d\n", fpclassify(u.f), isnormal(u.f));

}

输出(在Ubuntu上,用gcc编译,处理器x86)是:

sizeof(float) = 4
sizeof(int) = 4
0 00000001 00000000000000000000001
1.17549e-38
4 1

0 00000001 00000000000000000000000
1.17549e-38
4 1

1.17549e-38
3 0

84.75
84.75
4 1

0 00000000 11111111111111111100001
0x007fffe1
3 0
0 00000001 00000000000000000000000
0x00800000
4 1