我在 OS/X 64 位上运行 JDK 1.7。我认为这是一个错误……因为它不会出现在 Android 上,也不会出现在 Ubuntu Linux 上。也许它特定于我的 x86 处理器(今年早些时候刚购买)......不确定。
基本上,我想要一个时间...以纳秒或毫秒为单位...以 float 表示。当我运行下面的代码并将 System.nanoTime() 返回的 long 转换为 float 时, float 保持不变。 System.currentTimeMillis() 也会出现同样的问题。当然,时间(很长)正在改变......但是对 float 的转换完全失败了。它甚至失败了,因为我手动输入了一个很大的 long,如 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 是否为您而改变吗?也就是说,您是否没有遇到我所遇到的问题?
而且,这是怎么回事?有没有比我想出的方法更好的解决方法?
而且,这是一个错误吗?在哪一层?
最佳答案
float
的长度为 32 位。 long
的长度是 64 位。
主要问题是在两种类型之间转换时会损失一些精度。更具体地说,this case in the Java Language Specification明确涵盖:
A widening conversion of an int or a long value to float, or of a long value to double, may result in loss of precision - that is, the result may lose some of the least significant bits of the value. In this case, the resulting floating-point value will be a correctly rounded version of the integer value, using IEEE 754 round-to-nearest mode (§4.2.4).
您将获得"round-to-nearest"行为。
关于java - 在 OSX 上的 Java 中从大的 long 转换为 float 时出现错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24565397/