【问题标题】:Convert floating number to binary representation program in C将浮点数转换为C中的二进制表示程序
【发布时间】:2017-02-26 01:38:47
【问题描述】:
#include "ieee754.h"
#include <stdio.h>
#include <math.h>

//This program convert a floating number to its binary representation (IEEE754) in computer memory
int main() {
    long double f, binaryTotal, binaryFrac = 0.0, frac, fracFractor = 0.1;
    long int integer, binaryInt = 0;
    long int p = 0, rem, temp;

    printf("\nEnter floating number: ");
    scanf("%Lf", &f);

    //separate the integer part from the input floating number
    integer = (int)f;

    //separate the fractional part from the input floating number
    frac = f - integer;

    //loop to convert integer part to binary
    while (integer != 0) {
        rem = integer % 2;
        binaryInt = binaryInt + rem *pow(10, p);
        integer = integer / 2;
        p++;
    }

    //loop to convert fractional part to binary
    while (frac != 0) {
        frac = frac * 2;
        temp = frac;
        binaryFrac = binaryFrac + fracFractor * temp;
        if (temp == 1)
            frac = frac - temp;

        fracFractor = fracFractor / 10;
    }

    binaryTotal = binaryInt + binaryFrac;
    printf("binary equivalent = %Lf\n", binaryTotal);
}

我正在尝试将浮点数转换为二进制表示(64 位)。此代码有效,但并不完美。例如,当我转换.575 时,它给了我0.100100,但是当我使用这个网站http://www.exploringbinary.com/floating-point-converter/ 进行转换时,正确的输出应该是0.1001001100110011001100110011001100110011001100110011

我无法理解是什么让我的代码截断了数字。谁能帮我解决它?我感谢您的帮助。

【问题讨论】:

  • 编译时启用所有警告。
  • @MichaelWalz 没有警告:ideone.com/aIShip
  • @mike 你应该在. 之后写下你想要多少位数:"%.20Lf" 将打印0.10010011001100110011
  • @mike mch 是对的,我的评论在这里并不重要。
  • 那是因为数字不能完全用二进制(或double)表示。所以它只能打印最近的数字,可以保存在long double中。您应该将您的号码保存到一个字符串中。

标签: c floating-point binary converters


【解决方案1】:

很多问题:

  1. 使用(int) 提取long double 的整数部分严重限制了范围。使用modfl(long double value, long double *iptr);

    long double f;
    long int integer;
    //separate the integer part from the input floating number
    // Weak code
    integer = (int)f;
    
    long double ipart;
    long double fpart = modfl(f, &ipart);
    
  2. long p; pow(10,p); --> 一旦p 超过某个值,pow() 返回值就会丢失精度(示例 25)。将pow() 与使用long double 的函数一起使用也很奇怪。我希望powl()

  3. 各种其他不精确的 FP 问题:fracFractor/10long 的精度有限。

代码很奇怪,因为它试图将 FP 数字(可能是某种二进制格式)转换为二进制表示。它不应该在代码的任何地方都需要10

建议一些简单的东西,比如

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

static void print_ipart(long double x) {
  int digit = (int) (modfl(x/2, &x)*2.0) + '0';
  if (x) {
    print_ipart(x);
  }
  putchar(digit);
}

void print_bin(long double x) {
  // Some TBD code
  // Handle NAN with isnan()
  // Handle infinity with isfinite()

  putchar(signbit(x) ? '-' : '+');

  long double ipart;
  long double fpart = modfl(fabsl(x), &ipart);

  print_ipart(ipart);
  putchar('.');
  while (fpart) {
    long double ipart;
    fpart = modfl(fpart * 2, &ipart);
    putchar((int)ipart + '0');
  }
  putchar('\n');
}

int main() {
  print_bin(-4.25);
  print_bin(.575);
  print_bin(DBL_MAX);
  print_bin(DBL_MIN);
  print_bin(DBL_TRUE_MIN);
}

输出

-100.01
+0.1001001100110011001100110011001100110011001100110011001100110011
+1111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.
+0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
+0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001

【讨论】:

  • 感谢您的帮助!这是一种非常复杂的书写方式。虽然超出了我目前对 C 的熟悉程度.. 你能解释一下 (modfl(x/2, &x)*2.0) + '0' 是如何工作的吗?我发现 modfl 将 intpart 与 fracpart 分开,并且我看到了除以 2 的用途。我想我的问题是 &x 是做什么的,为什么要将它乘以 2?当 x%2 为 0 时,您是否将“0”放在最后?我认为这个转换器项目将是编写 C 代码的一个好习惯,但现在它有点超出我的理解。感谢您的帮助
  • @mike &amp;xx 的地址。 modfl(lf, addr)lf 分解为返回的小数部分和保存在讨论地址处的整数部分。函数结果是一个分数,在这段代码中,它将是 0.0 或 0.5。乘以 2 得到 0.0 或 1.0。将其添加到 '0' 会使 '0''1' 用于打印。希望这种方法比您原来的方法更简单。我不认为这超出了您的理解范围。
  • 好吧,现在很清楚了。非常感谢您的好意。
【解决方案2】:

这就是这不太可能奏效的原因:

fracFractor = 0.1
...
fracFractor = fracFractor/10

0.1 无法以任何二进制浮点格式准确表示。您不能将 0.1 表示为 2 的负数的倍数。将其除以 10 将使其在每一步都收集舍入误差。可能是因为您最终将一个重复分数与另一个重复分数进行比较,所以您让这个循环真正退出了。

这将严重限制您可以实现的目标:

binaryTotal = binaryInt + binaryFrac;

在浮点中执行此操作将有严重的限制 - 至少表示 0.1 不能如上所述表示。这就是为什么您会得到混合显示二进制和十进制数字的答案。

要解决这个问题,您可能应该查看数字的各个位。为了保持解决方案的整体思路完整,最简单的方法是从分数中减去 2 的负幂(0.5、0.25 等),测试它是否仍然是正数,并以此为基础构建一个字符串。然后对整数部分使用类似的逻辑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    • 1970-01-01
    • 2014-02-10
    • 2014-11-24
    • 2015-12-02
    • 2017-06-24
    • 2014-10-17
    相关资源
    最近更新 更多