C 中的浮点数不精确

float imprecision in C

提问人:Zaratruta 提问时间:5/18/2023 最后编辑:Eugene Sh.Zaratruta 更新时间:5/19/2023 访问量:131

问:

我开始学习 c 编程语言。 我知道浮动用以下方式表示:

  • 1 位符号
  • 指数为 8 位
  • 尾数为 23 位

这是否意味着我只能精确地表示精度为 23 位的实数? 也就是说,如果我想表示一个大于 2^23 的整数,它的表示将包括不精确性?

c 点浮 点精度

评论

1赞 T.J. Crowder 5/18/2023
至少相关:stackoverflow.com/questions/588004/......
2赞 T.J. Crowder 5/18/2023
您描述的格式是 IEEE-754 单精度二进制浮点。是的,与这种类型的所有二进制浮点格式一样,它存在精度问题。由于一些诡计,它更像是 24 位的精度而不是 23 位,但从根本上说,是的。
0赞 chux - Reinstate Monica 5/19/2023
@Zaratruta,典型可以精确地表示每个值和许多其他值。floatint25_t

答:

2赞 Eric Postpischil 5/18/2023 #1

除了对它的一些最低要求外,C 标准没有指定该类型使用什么格式。通常使用 IEEE-754 binary32 类型。在这种类型中,有限数表示为 ±2 e•f,其中 e 是整数 −126 ≤e ≤ 127,f 是 24 位(不是 23 位)二进制数字,基数点在第一个数字之后(所以 d.滴...DDD,其中每个 d 是 0 或 1,其中有 24 个)。float

F 称为有效。(尾数是对数分数部分的旧术语。有效是线性的。尾数是对数的。

浮点数编码为三个字段 SEF

  • S 表示 0 表示 +,1 表示 −。
  • 如果 f 的第一位为 1,则 Ee+127。如果 f 的第一位为 0,则 E 为 0。
  • Ff 的最后 23 位。

请注意,除非 e 为 −126,否则编码无法对 f 以 0 开头的浮点表示进行编码。但是,任何此类表示都可以通过将 f 中的位向左移动并减小 e 来转换为可编码表示,直到 f 的第一位为 1 或 e 为 −126。然后,新表示表示形式表示相同的数字并且是可编码的。

这是否意味着我只能精确地表示精度为 23 位的实数?

这意味着唯一可以表示的有限数是那些可以用 24 位或更少位表示的有限数,以及 −126 ≤ e ≤ 127 范围内的指数 e

也就是说,如果我想表示一个大于 2^23 的整数,它的表示将包括不精确性?

并非总是如此;230 是可表示的,因为它可以表示为 +2 30•1.0000000000000000000000000 2,而 2 30+27 是可表示的,因为它可以表示为 +230•1.000000000000000000000001 2.

超过 2 24 的整数可以表示,只要只需要24 个有效位来表示它们并且它们小于 2128

3赞 John Bollinger 5/18/2023 #2

我开始学习 c 编程语言。我知道浮动用以下方式表示:

  • 1 位符号
  • 指数为 8 位
  • 尾数为 23 位

这是 s 的典型表示形式,但 C 语言并不要求这样做。float

这是否意味着我只能精确地表示精度为 23 位的实数?

对于不是非常小(次正态)的非零值,您将获得一个隐式前导 1 位,因此您通常有 24 位尾数。但是,是的,这就是您必须使用的精度。

也就是说,如果我想表示一个大于 2^23 的整数,它的表示将包括不精确性?

使用这种浮点格式,您可以精确地表示绝对值小于 224 的所有整数。您还可以精确地表示一些较大的 - 其绝对值不超过最大可表示值的 1 并且其精确的二进制表示具有足够数量的尾随零。