【问题标题】:Some C Floating Point Constants Don't Make Sense一些 C 浮点常量没有意义
【发布时间】:2020-10-16 20:23:40
【问题描述】:

<float.h> 中的常量 Apple clang version 12.0.0 (clang-1200.0.32.2) 似乎没有意义。

DBL_MIN_EXP-1021DBL_MAX_EXP1024。但是,这与 wikipedia says 的内容不匹配,“指数范围从 -1022 到 +1023,...”

另外DBL_MIN_EXP 似乎与DBL_MIN 不一致,2.2250738585072014e-308 等于2⁻¹⁰²²,有时写为0x1.0000000000000p-1022。所以,我们有一个小于最小值-1021 的指数。

同样,DBL_MIN_10_EXP-307,鉴于 DBL_MIN 的指数为 e-308,这没有意义。

1024 的双倍 DBL_MAX_EXP 值在实际代码中使用时会溢出。例如,ldexp(1.0, 1024) 给出inf

这是我的 C 代码:

#include <float.h>
#include <stdio.h>
#include <math.h>

#define SHOW_DOUBLE(s)   printf("%.17lg \t%s\n", s, #s);
#define SHOW_INT(s)      printf("%d \t%s\n", s, #s);

int
main()
{
    SHOW_DOUBLE(DBL_MAX);
    SHOW_DOUBLE(DBL_MIN);
    SHOW_DOUBLE(DBL_EPSILON);
    SHOW_INT(DBL_MAX_EXP);
    SHOW_INT(DBL_MAX_10_EXP);
    SHOW_INT(DBL_MIN_EXP);
    SHOW_INT(DBL_MIN_10_EXP);
    SHOW_INT(DBL_DIG);
    SHOW_INT(DBL_MANT_DIG);
    SHOW_INT(FLT_RADIX);
    SHOW_INT(FLT_ROUNDS);
    printf("%lf\n", ldexp(1.0, 1024));
    return 0;
}

这是输出:

1.7976931348623157e+308 DBL_MAX
2.2250738585072014e-308 DBL_MIN
2.2204460492503131e-16  DBL_EPSILON
1024                    DBL_MAX_EXP
308                     DBL_MAX_10_EXP
-1021                   DBL_MIN_EXP
-307                    DBL_MIN_10_EXP
15                      DBL_DIG
53                      DBL_MANT_DIG
2                       FLT_RADIX
1                       FLT_ROUNDS
inf

【问题讨论】:

  • 你和其他系统的float.h文件比较了吗?我对 Windows 上的 gcc 有完全相同的结果
  • 好吧,从 C 标准来看:最小负整数,使得 FLT_RADIX 提升到 小于 1 是一个归一化的浮点数,emin
  • for max: /* 最大 int x 使得 FLT_RADIX**(x-1) 是一个可表示的浮点数 emax。 */

标签: c floating-point constants ieee-754


【解决方案1】:

一对一是规范的一部分。来自5.2.4.2.2 浮动类型的特征,¶11

...

  • 最小负整数,使得 FLT_RADIX 提高到 小于 1 幂是归一化浮点数 emin
    • FLT_MIN_EXP
    • DBL_MIN_EXP
    • LDBL_MIN_EXP

...

  • 最大整数使得 FLT_RADIX 提高到 小于 1 幂是可表示的有限浮点数 emax
    • FLT_MAX_EXP
    • DBL_MAX_EXP
    • LDBL_MAX_EXP

强调小于一个是我的。

【讨论】:

  • 当您了解这两个表示与表示浮点数的 C 模型相关的属性时,“小于”是有意义的(出现在标准的引用部分的开头) ,而不是直接极端数本身的性质。
  • @JohnBollinger:你能解释一下这有什么意义吗?
  • 浮点模型将数字表示为 (sign) * (FLT_RADIX ^ exponent) * (fraction),其中 fraction 介于 0(含)和 1(不含)之间,sign 为 1 或 -1。 *_MAX_EXP 和 *_MIN_EXP 是该公式中 exponent 参数的类型特定的最大值和最小值,因此它们非常自然。您从标准中引用的定义是根据生成的浮点值而不是根据模型来表达它们的,这种描述可能看起来令人惊讶。
  • @JohnBollinger:啊,所以因为“分数”在 [0,1) 中(如果您假设标准化,则实际上是 [0.5,1))而不是正常情况下的 [1,2)约定。
  • 是的,就是这样。
【解决方案2】:

我问了自己同样的问题,并意识到这是因为 IEEE 754 和 C 使用了两个不同的normalized forms

  • IEEE 754 对正常数使用介于 1(含)和 2(不含)之间的有效位

x = sign × significand × 2指数,编码为S|E|F 其中符号 = (-1)S ; 有效数 =

  • 1.F 如果 EminEEmax(正常数),
  • 0 如果 E = Emin - 1 且 F = 0(零),
  • 0.F 如果 E = Emin - 1 和 F ≠ 0(次正规数),
  • ∞ 如果 E = Emax + 1 且 F = 0(无穷大),
  • NaN 如果 E = Emax + 1 且 F ≠ 0(不是数字);

指数 = max(E, Emin) - 指数偏差 .

  • C 对 正常数 使用介于 0.5(含)和 1(不含)之间的 有效数'

x = sign′ × significand′ × 2exponent′,编码为 S|E|F 其中 sign′ = (−1)S ; 有效数' =

  • 0.1F 如果 EminEE max(正常数),
  • 0 如果 E = Emin - 1 且 F = 0(零),
  • 0.0F 如果 E = Emin − 1 且 F ≠ 0(次正规数),
  • ∞ 如果 E = Emax + 1 且 F = 0(无穷大),
  • NaN 如果 E = Emax + 1 且 F ≠ 0(不是数字);

指数′ = max(E + 1, Emin + 1) - 指数偏见

因为 x = 符号 × 有效数 × 2指数 = sign′ × significand′ × 2exponent′,IEEE 754规范化形式与C规范化形式的如下关系持有:

  • 符号' = 符号;
  • significand′ = significand/2;
  • 指数' = 指数 + 1.

尤其是 binary64 格式,这就是为什么 exponentmin = -1022 在 IEEE 754 规范化形式和 exponent'min = -1021,C 规范化形式 (DBL_MIN_EXP),exponentmax = 1023,IEEE 754 规范化形式,exponent'max = 1024,采用 C 规范化形式 (DBL_MAX_EXP)。

在 Python 中:

  • IEEE 754 归一化 significandexponent 可以通过以下方式提取:
math.ldexp(x, -math.floor(math.log2(x))), math.floor(math.log2(x))
  • C 归一化 significand′exponent′ 可以通过以下方式提取:
math.frexp(x)

例如:

>>> import math
>>> x = 12
>>> math.ldexp(x, -math.floor(math.log2(x))), math.floor(math.log2(x))
(1.5, 3)
>>> math.frexp(12)
(0.75, 4)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多