2011-01-10 12 views
9

Ich habe ein Problem auf UNIX-basierten Systemen sprintf nicht richtig aufrunden Wert.Rundungsdifferenzen auf Windows vs Unix-basierten System in sprintf

Zum Beispiel

double tmp = 88888888888885.875 
char out[512]; 

Das ist 88,888,888,888,885.875 nur um leichter auf die Augen. Ich gebe solch ein spezifisches und großes Beispiel, weil es scheint, dass es bei kleineren Zahlen gut funktioniert.

Ich versuche, es zu benutzen, in folgender Weise

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

Auf Fenster ergibt sich:

out = 000088888888888885.88 

On zum Beispiel AIX, zeigt aber in Linux auch:

out = 000088888888888885.87 

Warum passiert das? Irgendwelche Ideen und wie sie gleiche Art und Weise auf Win/Unix verhalten machen

Dank

+2

erm, http://www.ideone.com/UVtft meldet '.88', mein lokaler SuseLinux meldet das gleiche ... – Nim

+3

Welche CPUs verwenden Sie für jedes Betriebssystem? – chrisaycock

+0

Unter Linux (Debian 5) AMD64 bekomme ich '000088888888888885.88' –

Antwort

1

Es gibt eine bug report für Glibc mit einem Problem sehr ähnlich wie Ihres. Die wichtigste Schlussfolgerung (in Kommentar 46) ist, dass double keine 15-stellige Zahl ist und man nicht erwarten sollte, dass es so funktioniert.

Als Workaround können Sie Ihre Zahlen etwas kleiner hinzufügen, um sie besser zu runden. Diese Lösung ist jedoch nicht allgemeingültig, da sie von den Nummernbereichen abhängt, mit denen Sie arbeiten.

Eine andere Lösung kann sie vorzubereiten für die Rundung werden multipliziert, dann (zum Beispiel 2597.625*100 = 259762.5 -> 259763 = 2597.63*100) Rundungs ​​

Aber ich denke, es schlauer Abhilfen sein muss.

+0

Ich habe nicht Ihre Problemumgehung aber die Spitze Teil ist, was ich brauchte, danke – grobartn

0

Das ist, weil Sie verwenden double die Genauigkeitsbeschränkungen hat, das heißt, Ihre 88888888888885.875 ist wahrscheinlich sonst intern etwas abgerundet ist.

Weitere Informationen in a similar question, in blogs oder in wikipedia.

+3

Ja von warum ist das Doppel unterschiedlich auf den verschiedenen Betriebssystemen gerundet? Natürlich hat es Genauigkeitsgrenzen, deshalb bekommt er unterschiedliche Antworten. – Grammin

+2

Es kann von der Architektur der Box bis zu etwas Polieren variieren, das von libc's printf gemacht wird. Wie Sie von den Kommentaren zur Frage sehen können, verhält es sich sogar innerhalb desselben Betriebssystems (Linux) anders, da es im Wesentlichen keine Garantie gibt, dass es sich gleich verhalten sollte. –

0

Bei einer IEEE 754-konformen Implementierung sollte 88888888888885.88 im Standardrundungsmodus gedruckt werden. Dies hat nichts mit Gleitkomma-Genauigkeit zu tun, da der Wert genau darstellbar ist; es ist einfach eine Frage von printf Runden auf 2 Stellen nach dem Komma. Keine Ahnung, warum Sie auf einigen Systemen 88888888888885.87 sehen.

+1

Das OP möchte vielleicht versuchen, das 'sprintf' wegzulassen (und nur direkt einem Doppel zuzuordnen), um zu verifizieren, dass dies in' printf' geschieht. – Cascabel

1

Welche Fließkommadarstellungen werden von Ihrem Prozessor und Ihrem Compiler verwendet?

Nicht alle Prozessoren verwenden die gleiche Weise, um Fließkommawerte darzustellen, und sogar Compiler können andere Gleitkommadarstellungsmethoden wählen (ich denke, dass der Microsoft C++ - Compiler sogar Optionen zur Auswahl der Darstellung hat).

Die Seite http://www.quadibloc.com/comp/cp0201.htm gibt einen Überblick über einige der Gleitkommadarstellungen (obwohl sie dort als ziemlich alte Architekturen erscheinen).

http://msdn.microsoft.com/en-us/library/0b34tf65.aspx beschreibt, wie Microsoft Visual C++ Gleitkommawerte speichert. Ich konnte nicht sofort finden, welche Darstellung von AIX oder Linux verwendet wird.

Darüber hinaus verfügt jeder Compiler über Optionen, mit denen Sie angeben können, wie Sie mit Gleitkommaoperationen arbeiten möchten. Wollen Sie, dass sie so korrekt wie möglich sind (aber möglicherweise etwas langsamer)? Oder möchten Sie Gleitkommaoperationen so schnell wie möglich (aber möglicherweise weniger korrekt)?

+0

MSVC kann die Repräsentation nicht auswählen, ihre Optionen betreffen die Optimierungen, die sie für Gleitkommaarithmetik und Methoden ausführt. – Puppy

+0

Hier ist eine interessante verwandte Frage: http://stackoverflow.com/questions/1961442/different-math-rounding-behaviour-between-linux-mac-os-x-and-windows – mizo