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但是最小指数是-308在DBL_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_MAX与DBL_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实现.
以十进制指定二进制浮点数有微妙的问题.
为什么将值定义为带有后缀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数学确保常数不会无意中成为无穷大.
我希望以下的gcc和VS都不符合兼容的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.