在c中将十进制数转换为字符串

标签 c

我需要为一个项目重做printf,所以我实际上在float的转换上遇到了问题。 我成功地转换了几乎所有内容,但数字 1254451555.6
我遇到了一个问题:我收到 1254451555.59999

我认为保留 . 之后的部分的计算不起作用。

nbr = ((n - nbr) * 100000000);

我尝试了不同的方法,但还没有成功解决它。

你有什么想法吗?

  int               getlenghtitoa(long long n, int nbase)
  {
         int i;

         i = 0;
         while (n >= 0)
        {
          n /= nbase;
          i++;
          if (n == 0)
               break ;
        }
        return (i);
 }  

 float             ft_nbconv(float n, int i)
{
        while (i-- > 0)
        n = n *10;
        return (n);
 }

int                ft_power(long long nbr)
{
        int i;

        i = 1;
        while(nbr > 10)
        {
            i *= 10;
            nbr = nbr / 10;
         }
        return (i);
 }

char            *ft_conver_f(long double  n)
{
     char               *dest;
     int                    i;
     int                a;
     long long int          nbr;
     int                power;

     nbr = (long long) n;
     i  = getlenghtitoa((long long )n, 10);
     if (!(dest = malloc(sizeof(char) * (i + 8))))
       return (0);
     a = i;
     i = 0;
     power = ft_power(nbr);
     while (a--)
    {
        dest[i++] = ((nbr / power) % 10) + '0';
        if (power != 1)
            power /= 10;
    }
    dest[i++] = '.';
    nbr = ((n - nbr) * 100000000);
    power = 10000000;
    while (a++ < 5)
    {
        if (a == 5)
            if ((((nbr / power)) % 10) >= 5)
           {
               dest[i++] = ((nbr / power) % 10 + 1) + '0';
               break;
           }
        dest[i++] = ((nbr / power) % 10) + '0';
        power /= 10;
    }
    dest[i] = '\0';
    return (dest);
  }

最佳答案

大多数十进制分数不能精确地表示为二进制分数。其结果是,一般情况下,您输入的十进制 float 只是机器中实际存储的二进制 float 的近似值。

这就是为什么在实现 printf 时,真正能够将 float 转换为 2 位分隔整数的唯一方法是使用精度因子并手动舍入。 如果不需要实现精度,则默认为 6。 (精度是点后要打印的位数(并且是四舍五入的))。 这就是您的实现中所缺少的。 我们将点之前的数字称为 ipart ,将点之后的数字称为 fpart

nbr = ((n - nbr) * 100000000);

这应该是

nbr = ((n - nbr) * 10000000); // 7 zeros
// nbr is now equal to 5999999
if (nbr % 10 >= 5)
{
    nbr = nbr / 10 + 1;
}
else
    nbr = nbr / 10;

这样,你就得到了点后的7位数字,看看最后一位是否大于5,如果是,你在nbr上加上+1(除以10后确保nbr有 6 位数字),如果不是,则除以 10。

关于此舍入方法的另一个注意点是,它将无法将 fpart 舍入到 ipart 。 如果你想打印 3.9999999 该怎么办?它应该打印 4.000000。这意味着不能只是从头开始将 ipart 转换为字符串,因为有时舍入 fpart 会将 +1 添加到您的 ipart

因此,考虑创建一个函数ltoa,例如,它需要一个 long long int 并将其转换为字符串,完成我刚刚给您的关于舍入的代码段,以确保可以进行舍入到 ipart ,然后使用类似的东西将整个内容转换为字符串

dest = join(ltoa(ipart), ".", ltoa(fpart)).

还有一些注意事项,您的函数不处理负数。 而且你的int ft_pow很容易被淹没,所以考虑改为long long ft_pow

关于在c中将十进制数转换为字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58679722/

相关文章:

c - 在不退出 C 函数的情况下从函数返回一个值

c - 合并两个排序循环单链表

c - 编译 PortAudio 示例时出错

c++ - 如何在 opencv 中访问 yml 文件的元素?

c - 我在哪里可以找到 IJG libjpeg 的好教程

c - 当只有一个源发生变化时,Makefile 会重建所有对象

c - 扫描多个输入并根据真/假的数量输出 - 在 C 中

c - PCI_VDEVICE 和 PCI_DEVICE 有什么区别?

c - 双指针以及如何修改函数中的指针

c - popen with/dev/fd/n 匿名管道挂起子进程