【问题标题】:Is binary to decimal conversion rounded? how?二进制到十进制转换是否四舍五入?如何?
【发布时间】:2021-06-21 09:09:42
【问题描述】:

必须将二进制数转换为十进制以重新编码 printf(除 malloc 和 write 外,不允许任何库或函数)。我正在对 char * 进行计算,所以它不会溢出。但是当我达到一定的大小时,我的结果与在线二进制转换器不同,我注意到二进制转换器总是只保留 20 位。

例如:

  • 二进制:1.1111111111111111111111111
  • 二进制转换器 = 1.99999998509883880615,
  • 我的 o 转换器 == 1.99799896499882880605234375,

我猜在线转换器会将结果四舍五入为 unsigned long long,但我不明白这个四舍五入是如何计算的。

你有什么线索吗?

这是我的代码:

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

char *ft_binary_pow(char *tmp, int i)
{
    int j;
    int div;
    int remnant;

    j = 0;
    remnant = 0;
    tmp[0] = '1';
    tmp.sign = 0;
    while (i > 0)
    {
        while (isdigit(tmp[j]) || remnant != 0)
        {
            if (tmp[j])
                div = ((tmp[j] - '0') * 10) / 2;
            else
                div = 0;
            tmp[j] = ((div / 10) + remnant) + '0';
            remnant = div % 10;
            j++;
        }
        j = 0;
        i--;
    }
    return (tmp);
}

char  *ft_add_tmp(char *ret, char *tmp)
{
    int i;
    int j;
    int add;
    int remnant;

    i = strlen(tmp);
    add = 0;
    remnant = 0;
    while (--i >= 0)
    {
        if (!ret[i])
            add = tmp[i] - '0';
        else
            add = (ret[i] - '0') + (tmp[i] - '0');
        if ((add % 10 + remnant) < 10)
            ret[i] = (add % 10 + remnant) + '0';
        else
            ret[i] = '0';
        remnant = add / 10 ? 1 : 0;
    }
    return (ret);
}

int main(void)
{
    int i;
    char    *lol = "11111111111111111111111111";
    char    *ret;
    char    *tmp;

    if (!(ret = (char *)calloc(340, sizeof(char))))
        return (0);
    i = 0;
    ret[0] = '1';
    while (lol[i])
    {
        if (lol[i] == '1')
        {
            if (!(tmp = (char *)calloc(50, sizeof(char))))
            return (0);
            tmp = ft_binary_pow(tmp, i + 1);
            ret = ft_add_tmp(ret, tmp);
            free(tmp);
        }
        i++;
    }
    printf("ret = %s\n", ret);
    return (0);
}

为更易读的代码编辑

感谢您的宝贵时间!

【问题讨论】:

  • my o converter 是错误的 - 完全错误。贴出它的代码。可能是整数溢出。
  • 就像我说的,我正在使用 char * 进行计算,每个计算的最大可能数字是 19,所以 int 溢出不会成为问题。但我现在正在添加代码:)
  • 在英文中,什么是“calcul”?法语中的“计算”?
  • 如果没有看到您的代码,我们无法告诉您为什么您的代码出错。 “我正在使用 char * 进行计算” 什么也没告诉我们。你的代码是正确的,这当然不是任何形式的保证。
  • 我们如何知道别人看不见的代码是如何工作的?我们只能在这里讨论您的代码。也就是说,在线计算器是用 JavaScript 编写的,实际上所有人都可以通过页面检查看到。然而,Java 类型是动态的,因此没有“unsigned long long”——我查看了代码,它是使用 BigNumber.js 实现的,它完成了繁重的工作。

标签: c binary printf double decimal


【解决方案1】:

即使使用lol = "111111111",代码也会失败。

ft_add_tmp() 中的代码无法处理进入下一个最高有效数字的进位(溢出)。

else {
  ret.decimal[i] = '0';
  // add something like this and then also prorogate carry as needed to higher digits
  ret.decimal[i-1]++;  
}

建议的更正和简化:

char* ft_add_tmp(char *ret, const char *tmp) {
  size_t i = strlen(tmp);
  unsigned carry = 0;
  while (i-- > 0) {
    unsigned sum = ret[i] ? ret[i] - '0' : 0;
    sum += tmp[i] - '0' + carry;
    ret[i] = sum % 10 + '0';
    carry = sum / 10;
  }
  assert(carry == 0);
  return (ret);
}

【讨论】:

  • 老兄,非常感谢,我认为这很麻烦,因为只有一个数字是错误的......现在我的功能更加精确:D
  • @CanardWcs 提示:在调试和切断带有“这样它不会溢出”之类的结论的调查行时要小心。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-13
  • 1970-01-01
  • 1970-01-01
  • 2015-07-30
  • 2020-10-09
  • 2014-11-26
相关资源
最近更新 更多