6

我一直在从传感器读数中读取时间戳值,但由于它们以纳秒为单位提供,我想我会将它们转换为双倍并进行转换。结果数字是一个 17 位的值,加上分隔符。

尝试直接打印它会导致科学记数法,这是我不想要的,因此我使用 DecimalFormat 类将其输出到小数点后 4 位的预期值。问题是,即使调试器显示了 17 位十进制数字,即使在“doubleValue()”调用之后,输出字符串也显示了 15 位数字。

代码:

...
Double timestamp = (new Date().getTime()) +       // Example: 1.3552299670232847E12
            ((event.timestamp - System.nanoTime()) / 1000000D);
DecimalFormat dfmt = new DecimalFormat("#.####");

switch(event.sensor.getType()){
    case Sensor.TYPE_LINEAR_ACCELERATION:
    case Sensor.TYPE_ACCELEROMETER:
        accel = event.values.clone();
        String line = "A" + LOGSEPARATOR +              
            dfmt.format(timestamp.doubleValue()) + // Prints: 1355229967023.28
...

我认为这可能是一个 android 精度问题,但调试器的格式化程序也显示了错误的精度。我已经在本地 java 程序中对此进行了测试,两个调用的位数相同。

这是 DecimalFormat 错误/限制吗?还是我做错了什么?

4

3 回答 3

2

A double in Java has a mantissa of only 52 bit (counting the hidden 1 its 53 bit). This is equivalent to 15-16 decimal places (53*log10(2)). Every digit after this is kind of random and therefore it makes sense for the conversion function to cut the output after 15 decimal places.

Since you do not need the large number range that double provides, why not keep the value as long? This would give you 63 significant bits (64 -1 for the sign).

于 2012-12-21T15:21:25.113 回答
1

Java 和 Android 的 DecimalFormat 类之间确实存在差异,尽管采用完全相同的参数,但它们输出的结果也不同。

这足以让我尝试亨利的方法,现在我看到我已经获得了额外的 2 位精度。我也相信这些值是准确计算的,因为只涉及求和和乘法。

这是我最终使用的修改后的代码:

...
long javaTime = new Date().getTime();
long nanoTime = System.nanoTime();
long newtimestamp = javaTime * 1000000 +            // Compute the timestamp
            (event.timestamp - nanoTime);           // in nanos first
String longStr = Long.valueOf(newtimestamp).toString();
String tsString = longStr.substring(0, longStr.length()-6) +// Format the output string
            "." + longStr.substring(longStr.length()-6);    // to have the comma in the
                                                            // correct space.
...
于 2012-12-21T18:03:10.380 回答
0

正在对 String.format 进行一些研究,结果相同。

Double timestamp = 1.3552299670232847E12;
System.out.println("it was " + timestamp);
System.out.println("and now " + String.format("%.4f", timestamp));

这是输出:

12-12 15:48:58.255: I/System.out(2989): it was 1.3552299670232847E12
12-12 15:48:58.255: I/System.out(2989): and now 1355229967023,2800

也许你是对的,这是一个 Android 精度问题,就像你在 Java 中尝试一样,输出是正确的:http: //ideone.com/PBOiet

我会继续谷歌搜索...

于 2012-12-12T15:56:17.653 回答