我在OS / X上运行JDK 1.7,64位。我认为这是一个错误......因为它不会出现在Android上,也不会出现在Ubuntu Linux机器上。也许它特定于我的x86处理器(刚刚今年早些时候购买)......不确定。
基本上,我想要一个时间......以纳秒或毫秒......表示为浮点数。当我运行下面的代码,并将System.nanoTime()返回的long转换为float时,float保持不变。 System.currentTimeMillis()也会出现同样的问题。时间(很长)当然正在改变......但是浮动的时间是完全失败的。它甚至会失败,我手动输入1404434478024L。
for (int i=0; i<10; i++) {
// long timeL = 1404434478024L;
long timeL = java.lang.System.nanoTime();
// long timeL = java.lang.System.currentTimeMillis();
float timeF = timeL;
System.out.printf("%d: TimeL is %d. timeF is %f. ", i, timeL, timeF);
Long pTimeL = new Long(timeL);
float timeF2 = pTimeL.floatValue();
System.out.printf(" And timeF2 is %f.\n", timeF2);
}
Output:
0: TimeL is 1404435840046330000. timeF is 1404435888972234750.000000. And timeF2 is 1404435888972234750.000000.
1: TimeL is 1404435840046601000. timeF is 1404435888972234750.000000. And timeF2 is 1404435888972234750.000000.
2: TimeL is 1404435840046870000. timeF is 1404435888972234750.000000. And timeF2 is 1404435888972234750.000000.
3: TimeL is 1404435840047149000. timeF is 1404435888972234750.000000. And timeF2 is 1404435888972234750.000000.
4: TimeL is 1404435840047417000. timeF is 1404435888972234750.000000. And timeF2 is 1404435888972234750.000000.
5: TimeL is 1404435840047690000. timeF is 1404435888972234750.000000. And timeF2 is 1404435888972234750.000000.
6: TimeL is 1404435840047959000. timeF is 1404435888972234750.000000. And timeF2 is 1404435888972234750.000000.
7: TimeL is 1404435840048230000. timeF is 1404435888972234750.000000. And timeF2 is 1404435888972234750.000000.
8: TimeL is 1404435840048517000. timeF is 1404435888972234750.000000. And timeF2 is 1404435888972234750.000000.
9: TimeL is 1404435840048813000. timeF is 1404435888972234750.000000. And timeF2 is 1404435888972234750.000000.
这是我提出的修复/解决方法。
System.out.printf("\n Now, with the fix:\n");
for (int i=0; i<10; i++) {
// long timeL = 1404434478024L;
// long timeL = java.lang.System.nanoTime();
long timeL = java.lang.System.currentTimeMillis();
timeL = timeL % 1000000;
// Eliminate the high-order word...
// That is, keep only the lower digits under 1,000,000 seconds.
float timeF = timeL;
System.out.printf("%d: TimeL is %d. timeF is %f. ", i, timeL, timeF);
Long pTimeL = new Long(timeL);
float timeF2 = pTimeL.floatValue();
System.out.printf(" And timeF2 is %f.\n", timeF2);
}
Output:
Now, with the fix:
0: TimeL is 840049. timeF is 840049.000000. And timeF2 is 840049.000000.
1: TimeL is 840049. timeF is 840049.000000. And timeF2 is 840049.000000.
2: TimeL is 840049. timeF is 840049.000000. And timeF2 is 840049.000000.
3: TimeL is 840049. timeF is 840049.000000. And timeF2 is 840049.000000.
4: TimeL is 840050. timeF is 840050.000000. And timeF2 is 840050.000000.
5: TimeL is 840050. timeF is 840050.000000. And timeF2 is 840050.000000.
6: TimeL is 840050. timeF is 840050.000000. And timeF2 is 840050.000000.
7: TimeL is 840050. timeF is 840050.000000. And timeF2 is 840050.000000.
8: TimeL is 840051. timeF is 840051.000000. And timeF2 is 840051.000000.
9: TimeL is 840051. timeF is 840051.000000. And timeF2 is 840051.000000.
其他人想尝试运行上面的第一个代码摘录,让我知道timeF是否正在改变你?也就是说,你是否没有遇到我的问题?
而且,发生了什么?有没有比我提出的更好的解决方法?
而且,这是一个错误吗?在哪一层?
答案 0 :(得分:2)
float
长度为32位。 long
64位长。
主要问题是在两种类型之间进行转换时会丢失一些精度。更具体地说,明确涵盖了this case in the Java Language Specification:
将int或long值的扩展转换为float或long 值加倍,可能导致精度损失 - 即结果 可能会丢失该值的一些最低有效位。在这 case,生成的浮点值将是正确舍入的 使用IEEE 754舍入到最接近模式的整数值的版本 (§4.2.4)。
您获得了"round-to-nearest"行为。
答案 1 :(得分:2)
这是误用float
的情况,而不是错误。 float
类型的精度有限,正常数字为24位,相当于7位十进制数字。您的long
值在最重要的12位十进制数字中都是相同的,因此它们都会转换为相同的float
。
如果在你的时间间隔内有一个进位,那么抑制最重要的32位可能会产生不良影响。
System.nanoTime()
没有绝对意义。只有相对价值和差异才有意义。我建议在转换为long
或double
进行后续计算之前,从float
中减去每个nanoTime结果的第一个nanoTime结果。
答案 2 :(得分:0)
我无法评论,所以我会把它写成答案:
这是我得到的输出:
0: TimeL is 19799440493105. timeF is 19799440621568.000000. And timeF2 is 19799440621568.000000.
1: TimeL is 19799461838486. timeF is 19799461593088.000000. And timeF2 is 19799461593088.000000.
2: TimeL is 19799462215508. timeF is 19799461593088.000000. And timeF2 is 19799461593088.000000.
3: TimeL is 19799462573212. timeF is 19799461593088.000000. And timeF2 is 19799461593088.000000.
4: TimeL is 19799462915822. timeF is 19799463690240.000000. And timeF2 is 19799463690240.000000.
5: TimeL is 19799463295259. timeF is 19799463690240.000000. And timeF2 is 19799463690240.000000.
6: TimeL is 19799463587157. timeF is 19799463690240.000000. And timeF2 is 19799463690240.000000.
7: TimeL is 19799463867585. timeF is 19799463690240.000000. And timeF2 is 19799463690240.000000.
8: TimeL is 19799464241890. timeF is 19799463690240.000000. And timeF2 is 19799463690240.000000.
9: TimeL is 19799464598084. timeF is 19799463690240.000000. And timeF2 is 19799463690240.000000.
上面的代码运行完美,但问题可能是你的时间太大而无法转换为浮点数,所以请尝试使用双打代码。
希望这会有所帮助: 经典