漂浮小于FLT_MIN.为什么FLT_TRUE_MIN?

Vic*_*tor 6 c floating-point gnu99

试图看看在浮动下溢的情况下会发生什么,我发现我可以使浮点数比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;
}
Run Code Online (Sandbox Code Playgroud)

打印:
Float min为0.000000或1.175494e-38.
下溢为0.000000或4.203895e-45
Min float exp为-37.

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

chu*_*ica 7

获得"低于最低"的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()可能是其double产品FLT_MIN * 0.0000004.

    float underflow = FLT_MIN * 0.0000004;
    printf("%e\n", underflow);
    
    Run Code Online (Sandbox Code Playgroud)

    如果产出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();
Run Code Online (Sandbox Code Playgroud)

如果没有次正规数,则近似相同的2个数值FLT_MIN将具有非零的数学差异,FLT_MIN并且结果将舍入到0.0.

对于次正规数,每对不同floats 的差异可以用其他东西表示0.0.**

**除外+0.0, -0.0.签名零有自己的特点.


Dwa*_*ell 5

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

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