Frage

Also ich habe eine Funktion, die wie folgt aussieht:

float function(){
    float x = SomeValue;
    return x / SomeOtherValue;
}

Irgendwann, diese Funktion überläuft und gibt einen sehr großen negativen Wert.Zu versuchen, die Spur, wo genau das geschah, ich habe eine cout-Anweisung so, dass die Funktion wie folgt aussah:

float function(){
    float x = SomeValue;
    cout << x;
    return x / SomeOtherValue;
}

und es funktionierte!Natürlich, ich habe das problem gelöst, zusammen mit einem doppelten.Aber ich bin neugierig, warum die Funktion funktioniert, wenn ich couted es.Ist das typisch, oder könnte es ein bug irgendwo anderes, das mir fehlt?

(Wenn es ist jedem helfen, den gespeicherten Wert in der float ist einfach ein integer-Wert, und nicht besonders groß.Ich legte es in einen float zu vermeiden, Gießen.)

War es hilfreich?

Lösung

Willkommen in der wunderbaren Welt von floating-point.Die Antwort, die Sie bekommen, hängt wahrscheinlich davon ab, die floating-point-Modell, das Sie kompiliert den code mit.

Dies geschieht, weil der Unterschied zwischen den IEEE-Spezifikationen und der hardware der code ausgeführt wird.Deine CPU hat wahrscheinlich 80 bit floating-point-Register verwenden, um die 32-bit-float-Wert.Dies bedeutet, dass es weit mehr Präzision, während der Wert bleibt in einem register, als wenn er gezwungen ist, zu einem Speicher-Adresse (auch bekannt als 'homing' register).

Wenn Sie übergeben den Wert zu cout, den compiler zu schreiben hatte die floating-point-Speicher, und dies führt zu einem Verlust der Genauigkeit und Interessantes Verhalten WRT überlauf Fällen.

Siehe die MSDN-Dokumentation für VC++ floating-point-Schalter.Sie könnten versuchen, zu kompilieren mit /fp:strict und sehen, was passiert.

Andere Tipps

Druck einen Wert cout sollte nicht ändern Sie den Wert des Parameters in keinster Weise.

Ich habe allerdings gesehen, ein ähnliches Verhalten, das hinzufügen von debugging-Anweisungen bewirkt eine änderung in dem Wert.In diesen Fällen, und wahrscheinlich ist dies auch meine Vermutung war, dass der zusätzliche Anweisungen, die der compiler Optimierer, sich anders zu Verhalten, so generieren anderen code für Ihre Funktion.

Hinzufügen der cout-Anweisung bedeutet, dass vaue von x ist direkt verwendet.Ohne dass es die Optimierer könnten entfernen Sie die variable so ändern Sie die Reihenfolge der Berechnung und damit die änderung der Antwort.

Als beiseite, es ist immer eine gute Idee zu erklären, unveränderliche Variablen mit const:

float function(){
    const float x = SomeValue;
    cout << x;
    return x / SomeOtherValue;
}

Dadurch wird unter anderem verhindert, dass Sie versehentlich eine Weitergabe Ihrer Variablen auf Funktionen, die möglicherweise ändern Sie Sie nicht über-const Referenzen.

cout bewirkt, dass ein Verweis auf die variable, die oft Ursache der compiler zu zwingen, es zu verschütten, es auf den Stapel.

Denn es ist ein float, das wahrscheinliche Ursachen seiner Wert zu sein, abgeschnitten vom double oder long double-Darstellung Sie normalerweise haben.

Beim aufrufen einer Funktion (nicht-inline), die einen Zeiger oder eine Referenz auf x enden, verursacht das gleiche Verhalten, aber wenn der compiler später immer schlauer und lernt inline-es, werden Sie ebenso geschraubt :)

Ich glaube nicht, dass die cout hat keine Auswirkung auf die variable, die das problem haben würde, woanders zu sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top