这是Java中的代码片段:
int i = 1234567890;
float f = i;
System.out.println(i - (int)f);
为什么输出不等于0?它执行扩展,因此不应该丢失数据。然后,您只需截断该值。最好的祝福
这是Java中的代码片段:
int i = 1234567890;
float f = i;
System.out.println(i - (int)f);
为什么输出不等于0?它执行扩展,因此不应该丢失数据。然后,您只需截断该值。最好的祝福
看到不同
int i = 1234567890;
float f = i;
System.out.println(i - f);
System.out.println((int)f);
System.out.println(f);
System.out.println(i-(int)f);
输出:
0.0
1234567936
1.23456794E9
-46
你的错误在这里:
它执行扩展,因此不应该丢失数据。
这种说法是错误的。扩大并不意味着您不会丢失数据。
从Java规范:
扩大原始转换不会丢失有关数值整体大小的信息。
将 int 或 long 值转换为 float,或将 long 值转换为 double,可能会导致精度损失- 也就是说,结果可能会丢失值的某些最低有效位。在这种情况下,生成的浮点值将是整数值的正确舍入版本,使用 IEEE 754 舍入到最近模式(第 4.2.4 节)。
强调我的。
规范明确指出,量级不会丢失,但会丢失精度。
扩大这个词不是指数据类型的精度,而是指它的范围。浮点数比整数更宽,因为它们的范围更大。
整数
4 个字节,有符号(二进制补码)。-2,147,483,648 至 2,147,483,647。
漂浮
4 字节,IEEE 754。覆盖范围从 1.40129846432481707e-45 到 3.40282346638528860e+38(正或负)。
如您所见,float
具有更大的范围。但是,某些整数不能完全表示为浮点数。这种表示错误导致您的结果与 0 不同。存储在 f 中的实际值是 1234567936。
扩大可能会失去精度。Anint
具有 32 位精度,而 afloat
具有 25 位精度(24 位尾数和隐含的最高位)。Java 认为float
比 64 位更宽,long
恕我直言有点疯狂
由于精度有 8 位差异,误差可能高达 +/-64 左右,因为它将int
值四舍五入到最接近的float
表示。
int err = 0;
for (int i = Integer.MAX_VALUE; i > Integer.MAX_VALUE / 2; i--) {
int err2 = (int) (float) i - i;
if (Math.abs(err2) > err) {
System.out.println(i + ": " + err2);
err = Math.abs(err2);
}
}
印刷
... deleted ...
2147483584: 63
2147483456: -64
你会惊讶地发现,即使这是真的:
(f==(f+1))==true
给定f
的是一个足够大的浮点数......
int i = 1234567890;
float f = i;
System.out.println((int)f);
System.out.println(i);
System.out.println(i - (int)f);
输出是:
1234567936
1234567890
-46
看到不同。
比较整数浮点数具有更大的值。