2012-04-27 6 views
13

Kann jemand dieses Verhalten erklären? Ich bin mir der Darstellung von Gleitkommazahlen auf Maschinenebene sehr wohl bewusst. Dies scheint mit printf und seinen Formaten zu tun zu haben. Beide Zahlen werden genau durch Fließkomma-Notation dargestellt (Check: Multiplikation mit 64 ergibt eine ganze Zahl).printf-Rundungsverhalten für Doppel

#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); 
} 

Output:

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

Note, wird die erste Zahl abgerundet, und die zweite wird aufgerundet.

+1

Sie könnten in meinem Artikel http://www.exploringbinary.com/inconsistentroundingof-printed-floating-point-numbers/ interessiert sein. Einige Implementierungen verwenden "Rund-halb-weg von Null" anstelle von "halb-zu-gerade". –

+0

Es scheint, dass Microsoft das standardmäßige Rundungsverhalten zwischen VS 2010 und VS2015 geändert hat. Ich habe gerade von einem auf den anderen aufgerüstet und einige sehr nervige und subtile Bugs bekommen. [Dieses Blog] (https://blogs.msdn.microsoft.com/vcblog/2014/06/18/c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1 /) ist wahrscheinlich dazu gedacht, die Veränderung hervorzuheben, aber es wäre dir verziehen, sie komplett zu verpassen. – omatai

+0

es hängt von der Implementierung ab [Rundungsdifferenzen auf Windows vs Unix-basierten System in Sprintf] (http://Stackoverflow.com/q/4649554/995714), [C++ Rundungsverhalten Konsistenz für Bindungen mit Sprintf] (http: // Stackoverflow. com/q/31142600/995714) –

Antwort

17

Es ist "rund die Hälfte bis even" oder "Banker's Rundung". Die letzte Ziffer der gerundeten Darstellung ist so gewählt, dass sie gerade ist, wenn die Zahl genau zwischen den beiden liegt.

http://linuxgazette.net/144/misc/lg/a_question_of_rounding_in_issue_143.html:
„Für die GNU-C-Bibliothek, die Rundungsregel von printf() verwendet ist‚Banker‘oder‚Runde sogar‘Runden Dies ist richtiger als andere C-Bibliotheken, wie die C99-Spezifikation sagt. Diese Konvertierung in Dezimalwerte sollte den aktuell ausgewählten IEEE-Rundungsmodus verwenden (Standard-Banker-Rundung). "

+0

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

+1

Der Autor des verknüpften Artikels ist inkompetent. "Binär- und Dezimalradix teilen nicht die gleiche Menge irrationaler Zahlen" - das ist Unsinn. Rationalität/Irrationalität ist unabhängig von der Basis. –

+1

@R .. In der Tat. Aber die zitierte Passage des Artikels ist richtig, wie der Autor schmerzlich in seinem [Bugreport] (http://sourceware.org/bugzilla/show_bug.cgi?id=4943) gelernt hat. –

0

Der Ausgang %9.5f gibt die Nummer mit 5 Nachkommastellen an, die der Quellennummer am nächsten sind.