2011-01-10 12 views
9

Ho problemi con i sistemi basati su UNIX sprintf non arrotonda correttamente il valore.Differenze di arrotondamento su sistema basato su Windows vs Unix in sprintf

Per esempio

double tmp = 88888888888885.875 
char out[512]; 

Quello 88,888,888,888,885.875 solo per essere più facile per gli occhi. Sto dando un esempio così specifico e grande perché sembra che funzioni bene su numeri più piccoli.

Sto cercando di usarlo in modo seguente

sprintf(out, "%021.2f", tmp); 
printf("out = %s\n", tmp); 

Su Windows questo implica che:

out = 000088888888888885.88 

On per esempio AIX, ma mostra in Linux così:

out = 000088888888888885.87 

Perché sta succedendo questo? Tutte le idee e come renderlo comportarsi allo stesso modo su Win/Unix

Grazie

+2

erm, http://www.ideone.com/UVtft segnala ".88', il mio SuseLinux locale riporta lo stesso ... – Nim

+3

Quali CPU stai usando per ogni SO? – chrisaycock

+0

Su Linux (Debian 5) AMD64 Ottengo '000088888888888885.88' –

risposta

1

C'è una bug report per glibc con un problema molto simile al tuo. La conclusione principale (nel commento 46) qui è che il doppio non è un numero di 15 cifre decimali e non dovresti aspettarti che funzioni così.

Come soluzione alternativa, è possibile aggiungere qualcosa di piccolo ai numeri per renderli migliori. Ma questa soluzione non è generale perché dipende dalle gamme di numeri che gestisci.

Un'altra soluzione può essere moltiplicando per prepararli per l'arrotondamento, quindi arrotondamento (per esempio 2597.625*100 = 259762.5 -> 259763 = 2597.63*100)

tuttavia penso che ci deve essere soluzioni più intelligenti.

+0

Non ho usato la soluzione, ma la parte superiore parte è ciò di cui avevo bisogno, grazie – grobartn

0

Ecco perché si sta utilizzando double che ha limiti di precisione, significato, il vostro 88888888888885.875 viene probabilmente arrotondato a qualcos'altro internamente.

Vedere ulteriori informazioni in a similar question, in blogs o in wikipedia.

+3

Sì, perché il doppio viene arrotondato in modo diverso sui diversi SO? Ovviamente ha dei limiti di precisione, ecco perché sta ottenendo risposte diverse. – Grammin

+2

Può variare dall'architettura della scatola a una lucidatura eseguita da libf's printf. Come puoi vedere dai commenti alla domanda, anche all'interno dello stesso sistema operativo (Linux) si comporta in modo diverso, perché in sostanza non c'è alcuna garanzia che dovrebbe comportarsi allo stesso modo. –

0

Su un IEEE 754 conforme implementazione, dovrebbe stampare 88888888888885.88 nella modalità predefinita di arrotondamento. Questo non ha nulla a che fare con la precisione in virgola mobile poiché il valore è esattamente rappresentabile; si tratta semplicemente dell'arrotondamento di printf a 2 posizioni dopo il punto decimale. Non ho idea del perché stai vedendo 88888888888885.87 su alcuni sistemi.

+1

L'OP potrebbe voler provare ad omettere lo 'sprintf' (e semplicemente assegnando direttamente a un double) per verificare che ciò stia accadendo in' printf'. – Cascabel

1

Cosa virgola mobile rappresentazioni sono utilizzati dal processore e il compilatore?

Non tutti i processori usano lo stesso modo per rappresentare valori in virgola mobile e anche i compilatori possono scegliere diversi metodi di rappresentazione in virgola mobile (penso che il compilatore Microsoft C++ abbia anche opzioni per scegliere la rappresentazione).

La pagina http://www.quadibloc.com/comp/cp0201.htm fornisce una panoramica di alcune delle rappresentazioni in virgola mobile (anche se sembrano essere piuttosto vecchie architetture mostrate lì).

http://msdn.microsoft.com/en-us/library/0b34tf65.aspx descrive come valori in virgola mobile di Microsoft memorizza Visual C++. Non sono riuscito a trovare immediatamente quale rappresentazione è utilizzata da AIX o Linux.

Additinally, ogni compilatore dispone di opzioni che consentono di indicare come si desidera lavorare con operazioni in virgola mobile. Vuoi che siano corretti il ​​più possibile (ma forse un po 'più lenti)? O vuoi che le operazioni in virgola mobile siano il più veloci possibile (ma forse meno corrette)?

+0

MSVC non può scegliere la rappresentazione, le sue opzioni riguardano le ottimizzazioni che esegue su aritmetica in virgola mobile e metodi. – Puppy

+0

Ecco una interessante domanda correlata: http://stackoverflow.com/questions/1961442/different-math-rounding-behaviour-between-linux-mac-os-x-and-windows – mizo