c - 如何精确地将 float 转换为二进制

标签 c floating-point binary

我正在编写一个 C 函数,它允许我将任何 float 或 double 转换为包含 32 位 0 和 1 的字符串(根据 IEEE754 标准)。我不会使用 printf,因为目的是了解它的工作方式并能够存储字符串。

我从这个视频中获取了微积分方法:https://www.youtube.com/watch?v=8afbTaA-gOQ 。它使我能够将 float 解构为 1 位符号、8 位指数和 23 位尾数。

我得到了一些相当不错的结果,但我的转换器仍然不准确,而且我的尾数在最后几位经常是错误的。我用来计算尾数的方法是(其中 strnew 只是适当长度的 malloc):

   char *ft_double_decimals(double n, int len)
   {
        char    *decimals;
        int     i;

        if (!(decimals = ft_strnew(len)))
            return (NULL);
        i = 0;
        while (i < len)
        {
            n = n * 2;
            decimals[i++] = (n >= 1) ? '1' : '0';
            n = n - (int)n;
        }
        return (decimals);
    }

对于像 0.1 这样的 float ,我得到这个尾数:1001 1001 1001 1001 1001 100,我应该得到 1001 1001 1001 1001 1001 101。这太令人沮丧了!我显然在这里遗漏了一些东西,我想这与小数的错误近似有关,所以如果有人知道我应该使用什么方法而不是我正在使用的方法,我将非常感激! p>

最佳答案

my mantissa is often wrong in the last bits.

当转换不完整时,结果应四舍五入。 @Eric Postpischil

下面将中途情况从零舍入。

char *ft_double_decimals(double n, int len) {
  char *decimals;
  int i;

  if (!(decimals = ft_strnew(len)))
    return (NULL);
  i = 0;
  while (i < len) {
    n = n * 2;
    decimals[i++] = (n >= 1) ? '1' : '0';
    n = n - (int) n;
  }

  // Add rounding code
  if (n >= 0.5) {
    int carry = 1;
    while (i > 0) {
      i--;
      int sum = decimals[i] - '0' + carry;
      decimals[i] = sum % 2 + '0';
      carry = sum / 2;
    }
    if (i == 0 && carry > 0) {
      // Rounding into the "one's" digit"
      // TBD code to indicate to the caller that event
    }
  }

  return (decimals);
}

int main(void) {
  printf("%s\n", ft_double_decimals(0.1f, 23)); // --> 00011001100110011001101
  return 0;
}

更常见的舍入:将中途情况舍入到最接近的偶数。

if (n >= 0.5 && (n > 0.5 || ((i > 0) && decimals[i-1] > '0'))) {

此外,当舍入结果为 "1.00000..." 时,需要通知调用代码。

关于c - 如何精确地将 float 转换为二进制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53555365/

相关文章:

c - 当我尝试使用 realloc 将新行插入 2D-Array 时出现段错误

c++ - Gstreamer FLAC管道创建错误

c - double 和 float 可能具有相同的精度?

c++ - C语言打印时如何对浮点类型变量进行舍入?

c++ - 符合 IEEE-754 标准的四舍五入

c++ - 二进制字符串向后打印

c++ - #define 带有 L 标识符的语法

c - 当远程服务器可能在读取完成之前关闭套接字时,如何处理 C 中的套接字读取?

haskell - 在 Haskell 中从文件读取到数组

c - C中是否可以确定64位数字的具体数字