7

为了了解在浮点下溢的情况下会发生什么,我发现我可以使浮点数比 FLT_MIN 小得多。我在 OS 10.9 上使用 xcode 5.1。语言方言是gnu99。

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

int main(int argc, const char * argv[])
{
    float underflow = FLT_MIN * 0.0000004;

    printf("Float min is %f or %e.\nUnderflow is %f or %e\nMin float exp is %d.\n", FLT_MIN, FLT_MIN, underflow, underflow, FLT_MIN_10_EXP);

    return 0;
}

打印:
浮点最小值为 0.000000 或 1.175494e-38。
下溢为 0.000000 或 4.203895e-45
最小浮点 exp 为 -37。

  1. 有没有更有效的方法来证明数据类型的限制?
  2. 为什么 FLT_MIN 实际上不是最小的浮点值?我应该使用其他常量吗?输入上一个问题后,我找到了 FLT_TRUE_MIN。这个数字是多少?
4

3 回答 3

9

获得“低于最小值”的 2 种可能性:

  1. float范围:

    典型的float数字有 2 个范围:全精度(正常范围)从FLT_MAX下降到FLT_MIN和第二个范围,精度从FLT_MIN下降到FLT_TRUE_MIN. 第二个范围,称为“次正常”,通常提供大约 10^-7 的范围。

    FLT_TRUE_MIN是“最小正浮点数”

    FLT_MIN是“最小归一化正浮点数”

    FLT_MIN_10_EXP是“最小负整数,使得 10 的幂在归一化浮点数的范围内”

    C11dr §5.2.4.2.2

    一般来说0 < FLT_TRUE_MIN <= FLT_MIN <= 10^FLT_MIN_10_EXP <= 10^-37

  2. 数学表现为double

    printf()将每个float传递给它的内容转换为double. C 允许代码优化,使得传递给的值printf()可能doubleFLT_MIN * 0.0000004.

    float underflow = FLT_MIN * 0.0000004;
    printf("%e\n", underflow);
    

    如果输出是4.701976e-45而不是4.203895e-45,就会出现这种情况。


注意“不正常”。次正规(或非正规)数的一个令人信服的原因在于以下问题。

float a,b;
... // somehow a and b are set.

// Are the 2 below equivalent?
if (a == b) foo();
if ((a - b) == 0) foo();

如果没有次正规数,附近的 2 个几乎相同的值数字FLT_MIN将具有远低于零的非零数学差异FLT_MIN,结果将四舍五入为0.0.

对于次正规数,每对不同floats 的差异可以用 以外的东西来表示0.0。**

** 除外+0.0, -0.0。有符号零有自己的特点。

于 2014-09-07T00:07:35.377 回答
5

用非常简单而不准确的术语来说,浮点数存储为 0.xxxxx x 2^yyyyyy。“正常”数字要求在 xxxxxx 部分中不能有前导零。所以你能做的最小数字是 0.10000 x 2^-111111。但是,如果您“作弊”并将数字非规范化,您可以制作一个像 0.000001 x 2^-111111 这样的数字,它更小但有效数字更少。

http://en.wikipedia.org/wiki/Denormal_number

于 2014-09-06T22:46:40.493 回答
1

将浮点数表示为,如果您确定y = (+/-) significand x base ^ (exponent - precision),每个y != 0都有唯一的表示significand >= base ^ (precision - 1)y满足这一点的非零称为normalized。现在FLT_MIN是最小归一化正数floatFLT_TRUE_MIN而是在没有归一化限制的情况下得到的真正最小值。

换句话说,FLT_MIN = base ^ (FLT_MIN_EXP - 1)FLT_TRUE_MIN = base ^ (FLT_MIN_EXP - precision)

于 2014-09-06T22:59:54.267 回答