Java浮点澄清
我正在读Joshua Bloch的Java拼图。在谜题28中,我无法理解下面的段落- 这是因为浮点值越大,值越大 值与其后续值之间的距离。这种分配 浮点值是使用 有效位的固定数量。将1添加到浮点值 足够大的值不会更改该值,因为 不会“弥合”与继任者之间的差距Java浮点澄清,java,floating-point,Java,Floating Point,我正在读Joshua Bloch的Java拼图。在谜题28中,我无法理解下面的段落- 这是因为浮点值越大,值越大 值与其后续值之间的距离。这种分配 浮点值是使用 有效位的固定数量。将1添加到浮点值 足够大的值不会更改该值,因为 不会“弥合”与继任者之间的差距 为什么较大的浮点值与后续值之间的距离较大 如果是整数,我们添加一个以获得下一个整数,但是如果是浮点,我们如何获得下一个浮点值?如果我有IEEE-754格式的浮点值,我是否要在尾数部分加1以获得下一个浮点值 浮点数表示为尾数的组合 和指数,其
整数
,我们添加一个以获得下一个整数
,但是如果是浮点
,我们如何获得下一个浮点
值?如果我有IEEE-754格式的浮点值,我是否要在尾数部分加1以获得下一个浮点值尾数*
2^(指数)
如果我们假设尾数限制为2位
(为了使事情更简单)您有编号1.1*2^100
,
它非常大,“下一个”值将是1.2*2^100
。所以如果
您正在进行混合比例计算,1.1*2^100+1
将
四舍五入返回到1.1*2^100
,因为内存中没有足够的空间
尾数以保留准确的结果设想一种基于十进制的格式,其中只允许设置前5个值(即尾数长度为5)。对于较小的数字,您可以: 1.0000, 12.000, 125.00 但对于较大的数字,您将不得不开始截断,例如1113500。下一个可表示的数字是1113600,比100大。任何介于两者之间的值都不能用这种格式表示。如果您正在读取此范围内的值,则必须截断它-找到最接近的匹配表示,即使它不精确 这个数字越大,问题就越严重。如果我达到34567800000,那么下一个可代表的数字将是34567900000,这是1000000或一百万的差距。通过这种方式,您可以看到表示之间的差异取决于大小 在另一个极端,对于较小的值0.0001,下一个可表示的值为0.0002,因此间隙仅为0.0001
浮点值具有相同的原理,但采用二进制编码(二次方而非十次方)。尽管没有解释原因,但此示例代码显示了如何计算一个浮点值与下一个可用浮点值之间的距离,并给出了一个大数的示例
f
和g
应为整数。最大值应分开,但它们相同。下一个值是h
,它比109951162776
大
float f = Long.MAX_VALUE;
System.out.println("f = " + new BigDecimal(f));
System.out.println("f bits = " + Float.floatToIntBits(f));
float g = f - Integer.MAX_VALUE;
System.out.println("g = f - Integer.MAX_VALUE = " + new BigDecimal(g));
System.out.println("g bits = " + Float.floatToIntBits(g));
System.out.println("f == g? " + (f == g));
float h = Float.intBitsToFloat(Float.floatToIntBits(f) + 1);
System.out.println("h = " + new BigDecimal(h));
System.out.println("h bits = " + Float.floatToIntBits(h));
System.out.println("h - f = " + new BigDecimal(h).subtract(new BigDecimal(f)));
产出:
f = 9223372036854775808
f bits = 1593835520
g = f - Integer.MAX_VALUE = 9223372036854775808
g bits = 1593835520
f == g? true
h = 9223373136366403584
h bits = 1593835521
h - f = 1099511627776
你可以把浮点看作是以2为基数的科学记数法。在浮点运算中,尾数(又称有效位)和指数的位数是固定的。多少取决于您使用的是浮点(24位)还是双精度(53位)
对于10进制的科学记数法,我们更熟悉一些。假设尾数被限制为一个整数,并且始终由3个有效数字表示。现在在这表示中考虑这两对连续数:
- 100 x 100和101 x 100(100和101)
- 100 x 101和101 x 101(1000和1010)
请注意,第一对中的数字之间的距离(也称差)为1,而第二对中的数字之间的距离为10。在这两对中,尾数相差1,这是整数之间可能存在的最小差值,但差值按指数缩放。这就是为什么较大的数字在浮点运算中有较大的步长(您的第一个问题)
关于第二个问题,让我们看一下在数字1000(100 x 101)上加1(100 x 10-2):
- 100x101+100x10-2=1001x100
但尾数仅限于三个有效数字,因此最后一个数字将标准化(四舍五入后)为:
- 100 x 101
这让我们回到1000点。要更改浮点值,需要将该数字与下一个数字之间的差值至少加上一半;该最小差值随数字的大小而变化
二进制浮点也在发生同样的事情。还有更多细节(例如,规范化、保护数字、隐含基数点、隐含位),您可以在这篇优秀的文章中阅读