Double.MIN_NORMAL
(Java 1.6中引入)和 Double.MIN_VALUE
的区别?Double.MIN_NORMAL
(Java 1.6中引入)和 Double.MIN_VALUE
的区别?换句话说,只有在二进制小数点前面有数字1的情况下,对于单精度格式,普通数和次正常数之间的区别在于普通数的有效数字(二进制小数点左边的位)的首位为1,而次正常数的有效数字的首位为0。单精度格式的次正常数在 IEEE 标准 754 中被称为单精度格式的非规格化数。
Double.MIN_NORMAL
才是最小可能表示的数字。而Double.MIN_VALUE
基本上是没有这个限制的最小可表示数字。s_eee_eeee_eeee_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm_mmmm
(1秒; 3×4−1=11秒; 64−3×4=52秒)
,以及它的算法:
如果e >000_0000_0000
且<111_1111_1111
:解释为(-1)
s ×2e−balancer:1023 ×(
base:1 +m×2−sub-one-pusher:52)
。(这些是正常数。)
如果e =000_0000_0000
:做相同的事情(如上面的行),除了base:1
是base:0
,并且e
是e +1
。(这些是次正常数,除了零既不是次正常/正常数。)
如果e =111_1111_1111
且m =0000...0000
:解释为(-1)
s ×无穷大。
如果e =111_1111_1111
且m <>0000...0000
:解释为NaN。(顺便说一句:因此有2×(
252−1)
不同的位表示形式用于NaN,参见#Quiet NaN和doubleToRawLongBits
。)
它的最小正数是0_000_0000_0000_0000_..._0001
(Double.MIN_VALUE
(也是.NET的Double.Epsilon
)(一个次标准数)。
其可能的最小正常数为0_000_0000_0001_0000_..._0000
(Double.MIN_NORMAL
)。
MIN_VALUE
计算:
(-1)s:0 ×2(e:0+1)−balancer:1023 ×(base:0 +m:1 ×2−sub-one-pusher:52)
= 1 ×2−1022 ×2−52
= 2−1074 (~4.94 × 10−324)
,以及MIN_NORMAL
计算:
(-1)s:0 ×2e:1 −balancer:1023 ×(base:1 +m:0 ×2−sub-one-pusher:52)
= 1 ×2−1022 ×1
= 2−1022 (~2.225 × 10−308)
2^{1 + 52} - 2
,这是NaN位模式的数量。 - Mark Dickinsonm == 0
时有两种情况:一种是 s == 0
,另一种是 s == 1
。换句话说,对于 NaN 的位模式,s
有 2
种可能性,e
只有一种可能性,而 m
有 2^52 - 1
种可能性;相乘得到总共有 2 * (2^52 - 1) = 2^53 - 2
种可能性。 - Mark Dickinson为简单起见,本说明仅考虑正数。
两个相邻的标准化浮点数 'x1' 和 'x2'之间的最大间距是2 * epsilon * x1
(标准化浮点数不是均匀分布的,它们是对数分布)。这意味着,当一个实数(即“数学”数字)舍入为浮点数时,最大的相对误差是epsilon
,这是一个称为机器ε或单位舍入误差的常数,对于双精度,它的值为2^-52(近似值为2.22e-16)。
小于Double.MIN_NORMAL
的浮点数称为子规范数,并且它们填充0和Double.MIN_NORMAL
之间的间隙。这意味着涉及子规范数的计算可能导致不太准确的结果。使用子规范数允许计算在结果很小时更慢地失去精度。