为什么在以下代码中从int转换为float时会出现值丢失?
int value1 = 123456789; float value2 = value1; System.out.println(value1); System.out.println(value2);
输出:
123456789
123456792
float
类型使用与int
(32位)相同的位数来表示比int
用于表示仅整数更大范围内的浮点数。
这会导致精度损失,因为不是每个int
数都可以由float
精确表示。 只有24位用于表示数字的小数部分(包括符号位),而其他8位用于表示指数。
如果将此int
值分配给double
,则不会有任何精度损失,因为double
有64位,并且其中超过32位用于表示分数。
这是一个更详细的解释:
作为int的123456789的二进制表示forms为:
00000111 01011011 11001101 0001 0101
使用以下公式从其32位构造单精度浮点数:
(-1)^sign * 1.b22 b21 ... b0 * 2^(e-127)
sign
是最左边的位(b31)。 b22至b0是分数位,位b30至b23是指数e。
因此,当您将int
123456789转换为float
,您只能使用以下25位:
00000111 01011011 11001101 00010101 - --- -------- -------- -----
我们可以安全地摆脱任何前导零(除了符号位)和任何尾随零。 这将为您留下3个最低有效位,我们必须删除它们。 我们可以减去5得到123456784:
00000111 01011011 11001101 00010000 - --- -------- -------- -----
或者添加3以获得123456792:
00000111 01011011 11001101 00011000 - --- -------- -------- -----
显然,添加3可以得到更好的近似值。