6

Ho letto i valori di data/ora dalle letture del sensore, ma poiché sono forniti in nanosecondi, ho pensato di scriverli per raddoppiare e effettuare la conversione. Il numero risultante è un valore di 17 cifre, più il separatore.Formattazione Double per stampare senza notazione scientifica utilizzando DecimalFormat

Provare a stamparlo direttamente comporta una notazione scientifica, che non desidero, quindi uso una classe DecimalFormat per produrla con un valore previsto di 4 cifre decimali. Il problema è, anche se il debugger mostra un numero di 17 cifre decimali, anche dopo la chiamata 'doubleValue()', la stringa di output mi mostra un numero di 15 cifre.

Codice:

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

ho pensato che questo potrebbe essere un problema di precisione Android, ma il debugger ha il formattatore che mostra la precisione sbagliato pure. Ho provato questo in un programma java locale e entrambe le chiamate hanno la stessa quantità di cifre.

È un bug/limitazione DecimalFormat? O sto facendo qualcosa di sbagliato?

+1

Il tuo problema è che il numero non rientra nel formato. Provare "##############.####". –

+0

Anch'io ci ho provato, ma ho controllato comunque nel caso l'avessi dimenticato. Un formato "####################. ####" (con 7 cifre in più) valorizza lo stesso risultato. – ravemir

+0

Stai utilizzando la versione java.util di DecimalFormat o di Android? –

risposta

1

Esiste davvero una differenza tra la classe DecimalFormat di Android e di Android e producono risultati diversi, nonostante gli stessi esatti argomenti.

Questo è stato abbastanza per me per provare l'approccio di Henry, e ora che ho ho visto che ho guadagnato 2 punti di precisione in più. Sono anche sicuro che i valori siano calcolati in modo accurato, in quanto sono coinvolte solo somme e moltiplicazioni.

Questo è il codice modificato ho finito per usare:

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

Stava anche facendo qualche ricerca con String.format con gli stessi risultati.

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

E questo è l'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 

Forse hai ragione ed è un problema di precisione Android come se lo provate in Java, l'output è corretto: http://ideone.com/PBOiet

I Continueremo a googling ...

+0

Nessun nuovo risultato? – ravemir

2

Un doppio in Java ha una mantissa di soli 52 bit (contando il 1 nascosto a 53 bit). Questo è equivalente a 15-16 posizioni decimali (53 * log10 (2)). Ogni cifra dopo questo è casuale e quindi ha senso che la funzione di conversione taglia l'output dopo 15 posizioni decimali.

Dato che non è necessario l'ampio intervallo di numeri che fornisce il doppio, perché non mantenere il valore per tanto tempo? Questo ti darebbe 63 bit significativi (64 -1 per il segno).

+0

Questo era il mio ragionamento: ho bisogno di convertire i nanosecondi in millisecondi, calcolati con due lunghi. Ma non avevo pensato al contrario: cambio di millisecondi in nanosecondi, che non richiede dati in virgola mobile. In questo modo posso mantenere la precisione dai lunghi e ho solo bisogno di spostare la virgola di 6 posizioni a sinistra durante la stampa. Fammi provare questo e tornerò da te. – ravemir

+0

Ha funzionato! Non solo ho ottenuto gli altri due posti, ma anche un altro 2. La cosa strana è che mi aspettavo che gli ultimi due caratteri calcolati con il metodo precedente fossero solo numeri casuali, ma corrispondono a quelli del mio valore lungo appena calcolato. – ravemir

+0

Ti garantisco la taglia e aggiungo la mia risposta formattata. Mi sento un po 'stupido, però, perché ho pensato di fare qualcosa di simile a questo, ma non mi sono preoccupato/pensavo che fosse poco raccomandabile. – ravemir

Problemi correlati