2017-02-28 8 views
5

Ich hatte ein seltsames Verhalten mit meinem Programm, in dem der Doppelgänger die Präzision verlor. Meine Couts zeigten korrekte Werte, aber das Verhalten war immer noch unerwartet. Daher habe ich debuggt und festgestellt, dass sogar gdb unerwartete Werte zeigt. Im Folgenden nur die vereinfachte Szenario:gdb zeigt falschen doppelten Wert

double length =2.11; 
//gdb shows 2.10 here but prints 2.11 correctly using cout at the end 
cout<<"length; //It prints 2.11 correctly here 

Oft sind solche Fragen sind schwer auf Produktionsszenarien zu finden, wo das Debuggen nicht möglich ist und die einzige Option ist mit so viele Abzüge wie möglich. Irgendwelche Vorschläge, wie kann ich dieses Problem vermeiden?

+1

Falsche Frage (weil Sie vergessen haben, es zu motivieren, und tatsächlich ein [XY Problem] (http://xyproblem.info) haben ...). Wie Sie kommentiert haben, manipulieren Sie * Zahlen * nicht, aber eine Darstellung in barocker Länge (da Sie gesagt haben, '2.11' würde 2 Fuß und 11 Zoll bedeuten) –

+1

Wenn Sie' double' verwenden, sollten Sie mehrere Stunden brauchen, um http zu lesen: //floating-point-gui.de/ –

+0

@BasileStarynkevitch: Absolut guter Rat. Bewaffnet mit diesem Wissen gehen Sie auch auf Parties. – Bathsheba

Antwort

6

Angenommen IEEE754 double precision floating point, der nächste double bis 2.11 die etwas kleiner

2.109999999999999875655021241982467472553253173828125

std::cout geschickt genug ist, in geeigneter Weise durch Standard abzurunden, aber GDB erscheint auf 2 Dezimalstellen abgeschnitten werden.

+0

Wie vermeide ich das? Angenommen, ich habe eine Doppelvariable als 'double var = 2.11', wobei 2 für feets und 11 für inches steht, wie kann ich hier 0.11 Teile von hier extrahieren, da es immer 10 statt 11 ergibt – anurag86

+3

Das ist eine fragliche Verwendung eines' double', und nicht trivial zu lösen. Warum nicht ein 'struct' verwenden, das' Füße' und 'Zoll' separat modelliert? Sie könnten sogar eine "Normalisierungs" -Methode erstellen, die Dinge wie 1 Fuß 13 Zoll in 2 Fuß 1 Zoll umwandelt. – Bathsheba

+2

Eine solche Darstellung ist ein großer Fehler. 'double' sind * approximing * [reelle Zahlen] (https://en.wikipedia.org/wiki/Real_number). Ihre Daten sind nicht einmal eine Nummer. Entweder (und vorzugsweise) * wandeln sie es in eine gewisse Länge um (z.B.in * Meter *), oder etwas anderes behalten (ein 'std :: string', ein' std :: pair ') –

2

Angesichts der Tatsache, dass sich echte Zahlen so verhalten wie in Ihrem Fall, fürchte ich, dass es nicht viel zu tun gibt. Sie könnten geplant haben, dies zu vermeiden, und Platz geschaffen haben, um Gleichheitsprüfungen über Ihre doppelten Werte durchzuführen.

Hier sind zwei plausible Hacks für Sie:

1: [versucht, dies in einem College-Projekt] Um mit den Zahlen in der Größenordnung von 10^-4, verwenden Sie eine ganze Zahl und ein Faktorwert zu befassen. Beispiel: 1.2345 speichern, speichern wie Ganzzahl 12345 und als 10000 faktorieren. Jetzt können Sie korrekt drucken und dies gibt auch die Möglichkeit, Gleichheitsprüfungen auch zu tun.

2: Wenn die Genauigkeit der doppelten Werte bereits bekannt ist, können Sie einen Offset verwenden. Beispiel: Wenn 2.109999 eine Genauigkeit von 2 Dezimalstellen hat, verwenden Sie etwa Folgendes: (int) ((2.109999 + .005) * 100). Und dann drucken Sie entsprechend.

Aber diese beiden Hacks übernehmen folgende:

1: Sie haben die Kontrolle über die Genauigkeit der Werte. 2: Sie müssen wirklich genaue Werte drucken.