它不会输出错误的值。它只是输出一个您不期望的值。
重要的是这里发生了什么:
endTime - duration
这实际上被评估为:
(float) endTime - duration;
这就是数据丢失的地方。最接近float
1353728995 的值是 1353729024,最接近float
减 2 的结果仍然是1353729024。
这一切都遵循语言规范。JLS 第 15.8.2 节(加法运算符)指出二进制数字提升应用于操作数。
第 5.6.2 节(二进制数字提升)是这样开始的:
当运算符将二进制数值提升应用于一对操作数时,每个操作数都必须表示一个可转换为数值类型的值,以下规则按顺序适用:
因此,按照这些规则,将 的long
值endTime
转换为float
,然后在float
算术中执行减法。
请记住,afloat
仅提供 7 个有效数字的准确度,我希望其余的都相当明显。
请注意,如果没有将结果转换为long
,编译器会更清楚地说明发生了什么:
Test.java:8: error: possible loss of precision
long startTime = endTime - duration;
^
required: long
found: float
1 error
这清楚地表明,结果将是 a float
,这应该对操作将如何执行以及预期的准确性提出警告。