使用长双后缀L定义的浮点限制(双精度)

And*_*ing 5 floating-point gcc

1.问题:

我有一个关于这个问题DBL_MAX,并DBL_MIN在Linux中定义使用gcc v4.8.5.
它们的定义limit.h如下:

#define DBL_MAX     __DBL_MAX__
#define DBL_MIN     __DBL_MIN__
Run Code Online (Sandbox Code Playgroud)

在哪里__DBL_MIN____DBL_MAX__特定于编译器,可以通过以下方式获得:

$ gcc -dM -E - < /dev/null
...
#define __DBL_MAX__ ((double)1.79769313486231570815e+308L)
#define __DBL_MIN__ ((double)2.22507385850720138309e-308L)
...
Run Code Online (Sandbox Code Playgroud)

我的问题是:
为什么将值定义为long double后缀L,然后再将其转换为double

2.问题:

为什么__DBL_MIN_10_EXP__定义的-307但是最小指数是-308DBL_MIN宏中使用的?在最大指数的情况下,它被定义308,我可以理解,因为DBL_MAX宏使用它.

#define __DBL_MAX_10_EXP__ 308
#define __DBL_MIN_10_EXP__ (-307)
Run Code Online (Sandbox Code Playgroud)

不是问题的一部分,只是我做的观察:

通过使用Windows与Visual Studio 2015年的路上有只DBL_MAXDBL_MIN没有编译器的具体重定向的版本,以与下划线定义的宏.此外,最小正双精度值DBL_MIN和最大双精度值DBL_MAX比我的Linux gcc编译器的值略大(仅与上面gcc v4.8.5中定义的宏相比):

#define DBL_MAX        1.7976931348623158e+308
#define DBL_MIN        2.2250738585072014e–308
Run Code Online (Sandbox Code Playgroud)

而且Microsoft编译器设置了long doublea的值的限制double,似乎它不支持真正的long double实现.

chu*_*ica 5

以十进制指定二进制浮点数有微妙的问题.

为什么将值定义为带有后缀L的long double,然后再将其转换为double?

对于典型的binary64,最大有限值约为1.795e+308或精确.

179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
Run Code Online (Sandbox Code Playgroud)

转换为唯一所需的位数double可能多达DBL_DECIMAL_DIG (通常为17且至少为10).在任何情况下,使用指数表示法肯定是清楚的,而不是过于精确.

/*
1 2345678901234567 */          // Sorted 
1.79769313486231550856124...   // DBL_MAX next smallest for reference
1.79769313486231570814527...   // Exact
1.79769313486231570815e+308L   // gcc
1.7976931348623158e+308        // VS (just a hair closer to exact than "next largerst")
1.7976931348623159077293....   // DBL_MAX next largest if not limited by range
Run Code Online (Sandbox Code Playgroud)

各种编译器可能无法完全按照希望转换此字符串.有时会忽略一些最低有效数字 - 尽管这是由编译器控制的.

微妙转换差异的另一个来源,我希望这就是添加'L'的原因,double计算受到处理器浮点单元的影响,该单元可能没有完全符合IEEE标准.结果更糟的可能是在1.797...e+308不断转换到无穷远,由于转换微小错误"代码的double" 使用双数学.通过转换为a long double,那些long double转换错误非常小.然后将long double结果转换为double轮数到希望的数字.

简而言之,强制L数学确保常数不会无意中成为无穷大.

我希望以下的gccVS都不符合兼容的IEEE 754标准FPU.

#define __DBL_MAX__ 1.7976931348623157e+308
Run Code Online (Sandbox Code Playgroud)

演员回来double是做DBL_MAX一个double.这将满足许多代码的期望,即a DBL_MAX是a double而不是a long double.我看到没有规范需要这个.

为什么DBL_MIN_10_EXP定义为-307但最小指数为-308?

那是为了符合的定义DBL_MIN_10_EXP."...最小负整数,使10提升到该功率的范围是标准化浮点数"非整数答案在-307和-308之间,因此范围内的最小整数是-307.

观察部分

尽管VS将其long double视为一种不同的类型,但double使用的编码与使用的编码相同,因此使用时没有数字优势L.