java - 在 OSX 上的 Java 中从大的 long 转换为 float 时出现错误?

标签 java math casting

我在 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/

相关文章:

algorithm - 求解递归 T(n) = T(n/2) + lg n?

ios - swift : Segue(modal) to a UITableViewController which embeded in antoher navigation controller

java - Android Studio DatePicker/TimePicker 渲染/空指针异常问题?

java - 如何使用 Java 在 Raspberry Pi 3 上访问 BLE?

javascript - HTML, CSS, JS if 语句认为 1==0

java - 如何将坡度转换为度数,反之亦然?

java - 我对 java 和 c++ 之间的 "reference"感到困惑

java - jhipster不缓存查询结果

actionscript-3 - 如何在 Actionscript 3 中为我自己的类实现转换?

android - 无法在 getItem 中转换值