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.
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. 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.
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. I have tested this in a local java program and both calls have the same amount of digits.
Is this a DecimalFormat bug/limitation? Or am I doing something wrong?
double dexp = 12345678; System. out. println("dexp: "+dexp);
In the Format Cells window, (1) select the Number category, (2) set the number of decimal places to 0, and (3) click OK. Now the scientific notation is removed.
In Java, we can use String. format or DecimalFormat to format a double , both support Locale based formatting.
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).
There is indeed a difference between Java's and Android's DecimalFormat class, and they output different results, despite taking the exact same arguments.
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. 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.
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With