中DBL_TRUE_MIN的概念和听从

搬运自己2016年12月22日于SegmentFault宣布的篇章。链接:https://segmentfault.com/a/1190000007565915


在攻读C Prime
Plus的历程中遇见了这道复习题,利用搜索引擎加上自己的一对钻探,起首得出了定论,如有谬误之处,还望不吝赐教

下列循环中,倘若valuedouble品类,会见世什么样问题?

for (value = 36; value > 0; value /= 2)
  printf("%3d", value);

想来运行结果:要是valuedouble花色,总计过程中会导致极端循环(直到超越double品类的精度表示范围),又因printf以整型形式打印数字,会在结尾出现众两个数字0

答案中指明了这种气象的名词:浮点数下溢(underflow)

其实运行结果:

...(很多个0)
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0-21474836481073741824536870912-1879048192120795955260397977630198
98881509949447549747237748736188743689437184471859223592961179648589824294912147
4567372836864184329216460823041152576288144 72 36 18  9  4  2  1请按任意键继续.
. .

诚然出现了累累个0,但是在不少个0的背后又莫名其妙多出了一堆整数。为了分离出前边的长数字,修改格式化字符串为" %3d",结果如下:

...(很多个0)
0   0   0   0   0 -2147483648 1073741824 536870912 -1879048192 1207959552 603
979776 301989888 150994944 75497472 37748736 18874368 9437184 4718592 2359296 11
79648 589824 294912 147456 73728 36864 18432 9216 4608 2304 1152 576 288 144  72
36  18   9   4   2   1请按任意键继续. . .

为了更加弄掌握暴发这种现象的原故,继续修改格式化字符串为" %.3le",结果如下:

...
  4.663e-317 2.331e-317 1.166e-317 5.828e-318 2.914e-318 1.457e-318 7.285e-319 3
.643e-319 1.821e-319 9.107e-320 4.553e-320 2.277e-320 1.138e-320 5.692e-321 2.84
6e-321 1.423e-321 7.115e-322 3.557e-322 1.779e-322 8.893e-323 4.447e-323 1.976e-
323 9.881e-324 4.941e-324请按任意键继续. . .

可以看来,以整型输出的double体系变量实际上一直在调减,应该是double在内存中被截断读取为int此后导致了显示为整数的动静。

查看<float.h>头文件,找到三个和double品类精度有关的明示常量:

#define DBL_MIN          2.2250738585072014e-308 // min positive value
#define DBL_TRUE_MIN     4.9406564584124654e-324 // min positive value

可以见到,导致循环终止的因由是,循环中最终一个数字4.941e-324除以2后头的结果小于DBL_TRUE_MIN的值

为什么<float.h>中要利用DBL_MINDBL_TRUE_MIN四个颇具相同注释的常量?我第一使用搜索引擎查到了这么一个带注释的本子:

#ifndef DBL_TRUE_MIN
/* DBL_TRUE_MIN is a common non-standard extension for the minimum denorm value
 * DBL_MIN is the minimum non-denorm value -- use that if TRUE_MIN is not defined */
#define DBL_TRUE_MIN DBL_MIN
#endif

诠释部分忽视为,DBL_TRUE_MIN是对小小非规格化浮点数(Denormal
number
)
的通用非标准扩大,而DBL_MIN才是细微非规格化浮点数的值,并且只在DBL_TRUE_MIN未定义时行使。

C11标准 §5.2.4.2.2.13中涉嫌了DBL_TRUE_MIN

The values given in the following list shall be replaced by constant
expressions with implementation-defined (positive) values that are
less than or equal to those shown:
— minimum normalized positive floating-point number,
bemin−1
FLT_MIN 1E-37
DBL_MIN 1E-37
LDBL_MIN 1E-37
— minimum positive floating-point number
FLT_TRUE_MIN 1E-37
DBL_TRUE_MIN 1E-37
LDBL_TRUE_MIN 1E-37
(If the presence or absence of subnormal numbers is indeterminable,
then the value is intended to be a positive number no greater than the
minimum normalized positive number for the type.)

据悉地点查到的信息,我得出了以下的定论:

首先,浮点数在总计机中有规格化数和非规格化数二种象征方法。C标准在此地规定了二种浮点数的细微正值。具体值的轻重是由实现来定义的(由编译器等来支配),不过不可低于列出的那个值。并且,假使没有确定非规格化数是否会冒出,DBL_TRUE_MIN的值应该是一个低于等于该类型最小正规格化数DBL_MIN的值,FLT_TRUE_MINLDBL_TRUE_MIN同理。

自然想快点看完这本书的,结果遇上一个弄不懂的题目就查了很长日子……那一个实际上并不是一个好习惯。可是,反正自己要好曾经查过了,可能有无数个体了然不得法的地点,不过一旦可以协助到其别人,我发到这里的目的就直达了