简体   繁体   English

格式化使用DecimalFormat在没有科学记数法的情况下打印Double

[英]Formatting Double to print without scientific notation using DecimalFormat

I have been reading timestamp values from sensor readings, but since they are provided in nanoseconds, I thought I would cast them to double and make the conversion. 我一直在读取传感器读数的时间戳值,但由于它们以纳秒为单位提供,我认为我会将它们转换为加倍并进行转换。 The resulting number is a 17 digit value, plus the separator. 结果数字是一个17位数值加上分隔符。

Trying to print it directly results in scientific notation, which I don't want, so I use a DecimalFormat class to output it to an expected value of 4 decimal places. 试图直接打印它会产生科学记数法,这是我不想要的,因此我使用DecimalFormat类将其输出到4位小数的预期值。 The problem is, even though the debugger shows a number of 17 decimal digits, even after the 'doubleValue()' call, the output string shows me a number of 15 digits. 问题是,即使调试器显示了17个十进制数字,即使在'doubleValue()'调用之后,输出字符串也会显示15个数字。

Code: 码:

...
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
...

I thought this might be an android precision problem, but the debugger has the formatter showing the wrong precision as well. 我认为这可能是一个android精度问题,但调试器的格式化程序也显示错误的精度。 I have tested this in a local java program and both calls have the same amount of digits. 我在本地java程序中测试了这个,并且两个调用具有相同的数字量。

Is this a DecimalFormat bug/limitation? 这是一个DecimalFormat错误/限制吗? Or am I doing something wrong? 或者我做错了什么?

A double in Java has a mantissa of only 52 bit (counting the hidden 1 its 53 bit). Java中的double有一个只有52位的尾数(将隐藏的1计算为53位)。 This is equivalent to 15-16 decimal places (53*log10(2)). 这相当于15-16位小数(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. 此后的每个数字都是随机的,因此转换函数在15位小数后减少输出是有意义的。

Since you do not need the large number range that double provides, why not keep the value as long? 由于您不需要double提供的大数字范围,为什么不保持该值的长度? This would give you 63 significant bits (64 -1 for the sign). 这将给你63个有效位(符号为64 -1)。

There is indeed a difference between Java's and Android's DecimalFormat class, and they output different results, despite taking the exact same arguments. Java和Android的DecimalFormat类确实存在差异,尽管采用了完全相同的参数,但它们会输出不同的结果。

This was enough for me to try Henry's approach, and now that I have I see that I have gained an extra 2 places of precision. 这足以让我尝试亨利的方法,现在我已经看到我已经获得了额外的2个精度。 I am also confident that the values are calculated accurately, as only sums and multiplications are involved. 我也相信这些值是准确计算的,因为只涉及总和和乘法。

This is the modified code I ended up using: 这是我最终使用的修改后的代码:

...
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.
...

Was doing some research with String.format aswell with same results. 正在使用String.format进行一些研究以及相同的结果。

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

And this is the output: 这是输出:

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

Maybe you're right and it's an Android precision problem as if you try it in Java, the output is correct: http://ideone.com/PBOiet 也许你是对的,这是一个Android精度问题,就像你在Java中尝试一样,输出是正确的: http//ideone.com/PBOiet

I'll keep googling... 我会继续用Google搜索...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM