Float.MIN_VALUE和Float.MIN_NORMAL之间的区别?

Ash*_*ash 4 java floating-point double numbers

可能重复:
Double.MIN_NORMAL和Double.MIN_VALUE之间的差异

1)有人可以向我解释一下MIN_NORMAL和MIN_VALUE之间的区别是什么?

System.out.println(Float.MIN_NORMAL);
System.out.println(Float.MIN_VALUE);
Run Code Online (Sandbox Code Playgroud)

2)另外,为什么仍然打印1.0?

float f = Float.MIN_NORMAL + 1.0f;
System.out.println(f);

double d = Float.MIN_NORMAL + 1.0f;
System.out.println(d);
Run Code Online (Sandbox Code Playgroud)

输出:

1.17549435E-38
1.4E-45
1.0
1.0
Run Code Online (Sandbox Code Playgroud)

pic*_*ypg 7

第一个问题的答案是重复的.

第二个问题的答案是:

Floats和Doubles都没有无限精度.您可以方便地认为它们具有大约 16位精度.过去的任何事情,你将有舍入错误和截断.

因此,1.0e0 + 1e-38将无法做任何事情,除了因为截断额外精度而以1.0e0结束.

实际上,与答案的其余部分一样,它需要了解IEEE格式的浮点数实际上是如何以二进制形式添加的.基本思想是二进制浮点数的非符号和指数部分在CPU上的IEEE-754单元中移位(在英特尔上为80位宽,这意味着在结束时始终会截断计算)来表示其实数.在十进制中,这将是这样的:

Digit: 1 234567890123456
Value: 1.0000000000000000000000000000...0000
Value: 0.0000000000000000000000000000...0001

处理完添加后,实际上是:

Digit: 1 234567890123456
Value: 1.0000000000000000000000000000...0001

所以,用它记住,值截断周围的16位标记(十进制,这也正是22 二进制的32位浮点数字,51 二进制位在64位双,忽略了很重要的事实,即领先1被移位(相对于指数)并假定(有效地将23位二进制数字压缩为22位用于32位,52位用于51位用于64位);这是一个非常有趣的点,但您应该阅读更详细的示例,比如这里的细节).

截断:

Digit: 1 234567890123456
Value: 1.00000000000000000000

注意,真正小的小数部分被截断,因此留下1.

这是一个很好的页面,每当我在考虑内存中的实际表示时遇到问题我都会使用:十进制到32位IEEE-754格式.在该站点中,还有64位链接和反向链接.