Double.MIN_NORMAL和Double.MIN_VALUE之间的区别?
我可以知道Double.MIN_NORMAL (1.6中介绍)和Double.MIN_VALUE之间有什么区别吗?
Double.MIN_NORMAL
JavaDoc:
一个常量保持最小的正常值types
double
,2 -1022
Double.MIN_VALUE
JavaDoc:
一个常量保持最小的正数非零值types
double
,2 -1074
答案可以在IEEE浮点表示规范中find:
对于单一格式,正常数字和次正常数字之间的差别在于,正常数字的有效位的前导位(二进制位的左边的位)是1,而低于正常数的有效位的前导位数字为0.在IEEE标准754中,单格式的非正常数字被称为单格式非正规化数字。
换句话说, Double.MIN_NORMAL
是可以表示的最小可能数字,只要在二进制点前面有一个1(在十进制系统中被称为小数点)即可。 而Double.MIN_VALUE
基本上是没有这个约束的情况下可以表示的最小数字。
Tldr:
Double.MIN_NORMAL
给出了最小的正IEEE-754二进制64 “ 正常数 ”(也称为标准化数)。 这等于2 -1022 ,大约是2.225×10 -308 。
Double.MIN_VALUE
给出最小的正IEEE-754二进制64“ 次正常数 ”(也称为非规格化或次正规数)。 这相当于2 -1074 ,大约是4.94×10 -324 。 (这也是.NET的Double.Epsilon
给出的Double.Epsilon
。)
TSDR:
要理解为什么这些数字是他们是什么,他们之间有什么区别,我们将不得不更深入。 (也请阅读Bosonix的答案。)
考虑IEEE-754二进制64格式的比特表示:
s_eee_eeee_eeee_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm
IEEE-754的binary64值是这样得出的:
-
如果
e
大于0 且小于2047(2047是二进制的111_1111_1111
),那么值等于(-1) s × 2e-1023 ×(1 + m× 2-52 )。 (这是正常的数字。)
-
如果
e
等于0,那么值等于(-1) s ×2 (e + 1)-1023 ×(0 + m× 2-52 )。 (除零之外,这些是次正常数字。)
-
如果
e
等于2047并且m
等于0,那么值等于(-1) s × 无穷大 。
-
如果
e
等于2047并且m
不等于0,那么值等于NaN。 (不相关的事实:因此NaN有2×(2 52 – 1)个不同的位表示 ;参见
doubleToRawLongBits
。)
因此,最小的正IEEE-754二进制64正常数等于:
(-1) 0 ×2 1-1023 ×(1 + 0×2 -52 )
= 2 -1022
而最小的正IEEE-754二进制64次正常数等于:
(-1) 0 ×2 (0 + 1)-1023 ×(0 + 1×2 -52 )
= 2 -1022 ×2 -52
= 2 -1074
为了简单起见,解释只考虑正数。
两个相邻的归一化浮点数 “x1”和“x2”之间的最大间隔是2 * epsilon * x1
(归一化浮点数不是均匀间隔的,它们是对数间隔的)。 这意味着,当一个实数 (即“math”数)四舍五入到一个浮点数时,最大相对误差是epsilon
,它是一个称为机器ε或单位舍入的常量,对于双精度,它具有值2 ^ -52(近似值2.22e-16)。
小于Double.MIN_NORMAL
的浮点数称为次正规,它们均匀填充0到Double.MIN_NORMAL
之间的间隔。 这意味着涉及低于正常值的计算会导致不准确的结果。 当结果很小时,使用低于正常的标准可以使计算更加缓慢地失去精度。