【问题标题】:C - Printing a float - loss of precision when casting to int [duplicate]C - 打印浮点数 - 转换为 int 时精度损失 [重复]
【发布时间】:2014-11-04 22:39:37
【问题描述】:

我正在尝试制作一个可以打印浮点数的函数。 现在,我遇到了两种奇怪的行为: 有时,像 1.3 这样的值会显示为 1.2999999 而不是 1.3000000,有时像 1.234567 这样的值会显示为 1.2345672 而不是 1.2345670。

这里是源代码:

int     ft_putflt(float f)
{
    int     ret;
    int     intpart;
    int     i;

    ret = 0;
    i = 0;
    intpart = (int)f;
    ft_putnbr(intpart);
    ret = ft_nbrlen(intpart) + 8;
    write(1, ".", 1);
    while (i++ < 7)
    {
        f *= 10;
        ft_putchar(48 + ((int)f % 10));
    }
    return (ret);
}

ft_putnbr 没问题,AFAIK。 ft_putchar 是对“write(1, &c, 1)”的简单调用。

test values (value : output)

1.234567  : 1.2345672 (!)

1.2345670 : 1.2345672 (!)

1.0000001 : 1.0000001 OK

0.1234567 : 0.1234567 OK

0.67      : 0.6700000 OK

1.3       : 1.3000000 OK (fixed it)

1.321012  : 1.3210119 (!)

1.3210121 : 1.3210122 (!)

这一切对我来说似乎有点神秘......转换为 int 时可能会丢失精度?

【问题讨论】:

  • 精度损失不是很大,而是一开始就缺乏精度。 float 只能准确表示大约 7 位小数。如果您想要更多,请尝试double
  • 欢迎来到浮点数学。您注意到的任何“症状”都不是意外或异常的。
  • 哼...有没有办法解决这些“症状”?
  • @SwiX 是的。使用定点数而不是浮点数。
  • 好的,谢谢。我并没有像我希望的那样深入了解其背后的机制,但必须这样做 - 该功能仍然足够准确,可以达到它的目的;)

标签: c++ c casting output


【解决方案1】:

是的,在处理浮点数和整数时会丢失精度。

如果两个浮点数的大小不同,并且都使用完整的精度范围(大约 7 个十进制数字),那么是的,您会在最后几个位置看到一些损失,因为浮点数以 (sign) 的形式存储(尾数) × 2(指数)。如果两个值具有不同的指数并且您将它们相加,那么较小的值将减少到尾数中的较少位数(因为它必须适应较大的指数):

PS> [float]([float]0.0000001 + [float]1)
1

关于整数,一个普通的 32 位整数能够准确地表示不完全适合浮点数的值。浮点数仍然可以存储大约相同的数字,但不再精确。当然,这只适用于足够大的数字,即。 e.长于 24 位。由于浮点数具有 24 位精度,而(32 位)整数具有 32 位,浮点数仍然能够保留幅度和大部分有效数字,但最后的位置可能会有所不同:

PS> [float]2100000050 + [float]100
2100000100

【讨论】:

    【解决方案2】:

    这是使用有限精度数值表示方案所固有的。给定任何可以表示的数,A,有一些比 A 可以表示的最小的数,称为 B。A 和 B 之间的数不能精确表示,必须近似。

    例如,让我们考虑使用六位十进制数字,因为这是一个更容易理解的系统作为起点。如果 A 是 0.333333,那么 B 是 0.333334。 A 和 B 之间的数字,例如 1/3,无法准确表示。因此,如果您取 1/3 并将其与自身相加两次(或将其乘以 3),您将得到 0.999999,而不是 1。您应该期望在表示的极限处看到不精确性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-02
      • 2011-02-01
      • 1970-01-01
      • 2019-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-26
      相关资源
      最近更新 更多