2012-04-27 14 views
13

Qualcuno può spiegare questo comportamento? Sono ben consapevole della rappresentazione a livello macchina dei numeri in virgola mobile. Questo sembra essere correlato a printf e ai suoi formati. Entrambi i numeri sono rappresentati esattamente dalla notazione in virgola mobile (verificare: moltiplicando per 64 si ottiene un numero intero).comportamento di arrotondamento printf per i doppi

#include <stdio.h> 
#include <iostream> 
using namespace std; 

int main() { 
    double x1=108.765625; 
    printf("%34.30f\n", x1); 
    printf("%9.5f\n", x1); 
    printf("%34.30f\n", x1*64); 

    double x2=108.046875; 
    printf("%34.30lf\n", x2); 
    printf("%9.5f\n", x2); 
    printf("%34.30f\n", x2*64); 
} 

uscita:

> 108.765625000000000000000000000000 
> 108.76562 
> 6961.000000000000000000000000000000 
> 108.046875000000000000000000000000 
> 108.04688 
> 6915.000000000000000000000000000000 

nota, il primo numero viene arrotondato verso il basso, e il secondo viene arrotondato.

+1

Potresti essere interessato al mio articolo http://www.exploringbinary.com/inconsistent-rounding-of-printed-floating-point-numbers/. Alcune implementazioni usano "round-half-from-zero" invece di "round-half-even". –

+0

Sembra che Microsoft abbia cambiato il comportamento di arrotondamento predefinito tra VS 2010 e VS2015. Ho appena aggiornato da uno all'altro e ho ottenuto alcuni bug molto fastidiosi e sottili. [Questo blog] (https://blogs.msdn.microsoft.com/vcblog/2014/06/18/c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1 /) è probabilmente pensato per evidenziare il cambiamento, ma ti verrebbe perdonato per averlo perso completamente. – omatai

+0

dipende dall'implementazione [Arrotondamento differenze su sistema basato su Windows vs Unix in sprintf] (http://stackoverflow.com/q/4649554/995714), [C++ Corrispondenza comportamento arrotondamento per legami con sprintf] (http: // stackoverflow. com/q/31142600/995714) –

risposta

17

È "round half to even" o "banker's rounding". L'ultima cifra della rappresentazione arrotondata viene scelta per essere anche se il numero è esattamente a metà strada tra i due.

http://linuxgazette.net/144/misc/lg/a_question_of_rounding_in_issue_143.html:
"Per la libreria GNU C, la regola di arrotondamento usato da printf() è 'banchieri arrotondamento' o 'round per addirittura' Questo è più corretta di alcune altre librerie C, come la specifica C99 dice. la conversione in decimale dovrebbe utilizzare la modalità di arrotondamento IEEE attualmente selezionata (arrotondamento predefinito dei banchieri). "

+0

anche: http://www.gnu.org/software/libc/manual/html_node/Rounding.html –

+1

L'autore dell'articolo collegato è incompetente. "Il radix binario e decimale non condivide lo stesso insieme di numeri irrazionali" - non ha senso. La razionalità/irrazionalità è indipendente dalla base. –

+1

@R .. In effetti. Ma il passaggio citato dell'articolo è corretto, come l'autore ha imparato dolorosamente nel suo [bug report] (http://sourceware.org/bugzilla/show_bug.cgi?id=4943). –

0

L'uscita %9.5f fornisce il numero con 5 cifre dopo il punto decimale che è il più vicino del numero sorgente.

Problemi correlati