1。 问题:
我对使用gcc v4.8.5的Linux中的DBL_MAX
和DBL_MIN
定义提出了疑问。
它们在limit.h
中定义为:
#define DBL_MAX __DBL_MAX__
#define DBL_MIN __DBL_MIN__
其中__DBL_MIN__
和__DBL_MAX__
是编译器特定的,可以通过以下方式获取:
$ gcc -dM -E - < /dev/null
...
#define __DBL_MAX__ ((double)1.79769313486231570815e+308L)
#define __DBL_MIN__ ((double)2.22507385850720138309e-308L)
...
我的问题是:
为什么这些值定义为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)
不是问题的一部分,只是我做的观察:
顺便使用Windows和Visual Studio 2015,只有DBL_MAX
和DBL_MIN
宏定义,而没有编译器特定的重定向到带有下划线的版本。此外,最小正双精度值DBL_MIN
和最大双精度值DBL_MAX
比我的Linux gcc编译器的值稍微大一点(刚好与上面gcc v4.8.5中定义的宏相比): / p>
#define DBL_MAX 1.7976931348623158e+308
#define DBL_MIN 2.2250738585072014e–308
此外,Microsoft编译器将long double
限制设置为double
的值,似乎它不支持真正的long double
实现。
答案 0 :(得分:5)
指定十进制的二进制浮点数有微妙的问题。
为什么将值定义为带有后缀L的long double,然后再将其转换为double?
对于典型的binary64,最大有限值约为1.795e+308
或完全相同。
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
转换为唯一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
各种编译器可能无法完全按照希望转换此字符串。有时会忽略一些最低有效数字 - 尽管这是由编译器控制的。
微妙的转换差异的另一个来源,我希望这就是为什么&#39; L&#39;已添加,double
计算受处理器浮点单元的影响,该单元可能没有完全符合IEEE标准。更糟糕的结果可能是1.797...e+308
常量转换为无穷大由于分钟转换错误导致double
&#34; 使用双数学。通过转换为long double
,这些long double
转换错误非常小。然后将long double
结果转换为double
轮到期望的数字。
简而言之,强制L
数学确保常量不会无意中成为无穷大。
我希望以下 gcc 和 VS 都不符合兼容的IEEE 754标准FPU。
#define __DBL_MAX__ 1.7976931348623157e+308
强制转回double
会使DBL_MAX
成为double
。这符合许多代码的期望,即DBL_MAX
是double
而不是long double
。我认为没有规范要求这样做。
为什么 DBL_MIN_10_EXP 用-307定义但最小指数是-308?
这是为了遵守DBL_MIN_10_EXP
的定义。 &#34; ...最小负整数,使得提升到该幂的10在标准化浮点数的范围内&#34;非整数答案在-307和-308之间,因此范围内的最小整数是-307。
观察部分
虽然VS将long double
视为不同类型,但使用与double
相同的编码,因此使用L
时没有数字优势。
答案 1 :(得分:1)
我不知道为什么使用L后缀。
This网站概述了IEEE 754浮点数。
指数为11位,偏移量为1023.但是0和2047的指数是为特殊数字保留的。所以这意味着指数可以从2046-1023 = 1023变化到1-1023 = -1022。
因此,对于最大标准化值,我们的指数为2 ^ 1023。尾数的最大值刚好低于2(1.111等,点后52 1 1s,二进制),即~2 * 2 ^ 1023 = ~1.79e308。
对于最小标准化值,我们的指数为2 ^ -1022。最小尾数正好为1,给出的值为1 * 2 ^ -1022 = ~2.22e-308。到目前为止一切都很好。
DBL_MIN_10_EXP和DBL_MAX_10_EXP是规范化的10的最小/最大指数。因为最大1e308小于~1.79e308所以值为308.对于最小值,1e-308太小 - 它低于~2.22e-308。 1e-307大于~2.22e-308,因此值为-307。