2015-05-14 4 views
13

Ich verstehe Gleitpunkt hat Rundungsfehler, aber ich frage mich, ob es bestimmte Situationen gibt, in denen der Fehler nicht gilt, wie z. B. die Multiplikation mit Null.Ist die Multiplikation von Gleitkommazahlen mit Null garantiert Null?

Ist Null mal eine Zahl = Null für alle Fließkommazahlen?

+3

Abgesehen von speziellen Werten wie NaN, Infinity oder -Infinity, ist es richtig anzunehmen, dass jede normale Zahl multipliziert mit genauem Null genau Null ergibt. –

Antwort

19

False:

0f * NAN == NAN 
0f * INFINITY == NAN 

und ...

0f * -1f == -0f (negative 0f), with 0f == -0f :-) 

(auf Intel, VC++, und wahrscheinlich auf jeder Plattform, die IEEE 754-1985 Gleitpunkte verwendet)

Beispiel auf ideone (das wahrscheinlich GCC auf einigen Intel-kompatiblen Plattformen verwendet)

+4

Ja, dies ist bei jedem System garantiert, das IEEE-754 entspricht (aber um ganz klar zu sein: -0 ist immer noch "Null"). –

+2

@StephenCanon Es ist immer noch "0" in dem Sinne, dass "0f == -0f", aber zum Beispiel, wenn Sie "-0f * INFINITY" multiplizieren und das Ergebnis drucken, erhalten Sie "-NaN", so ist es immer noch "0", aber sein Vorzeichen kann verwendet/extrahiert werden. http://ideone.com/L6MQlQ – xanatos

+2

Das Signbit eines NaN hat keine Bedeutung, es gibt also weder "-NaN", noch wird "-0 * inf" garantiert "-NaN" (it könnte einen ruhigen NaN-Wert erzeugen). Das Zeichen "-0" kann jedoch auf andere Weise extrahiert werden. –

2

Zusätzlich einige OPs middle-of-the-post Anliegen @xanatos feine Antwort, betrachtet:

Ich frage mich, ob es bestimmte Situationen, in denen die (Rundung) Fehler nicht

Kandidaten gelten umfassen some_double_y = some_double_x * 1.0 und some_double_y = some_double_x + 0.0 können niemals einen Rundungsfehler verursachen.

Doch selbst diejenigen sind verdächtig aufgrund eines Compilers kann double mit höherer Genauigkeit unter Berücksichtigung der FLT_EVAL_METHOD == 2 bewerten, wo „alle Operationen und Konstanten auf den Bereich und die Genauigkeit der long double Art bewerten.“ In diesem Fall kann ein Zwischenprodukt some_double_x als long double vorliegen, das sich von einem scheinbaren double-Wert von 0.0 oder 1.0 unterscheidet.

+0

Ich bin mir nicht sicher, ob ich einem "intermediate some_double_x" als long double folgen kann, das sich von einem scheinbaren doppelten Wert von 0.0 oder 1.0 unterscheidet. Wenn some_double_x eine doppelte Variable ist, I Verstehst du, dass es zu einem langen Doppelzählen umgewandelt werden kann, mit null/multipliziert mit eins (was no-op sein sollte, oder?), und dann zurück in das Doppelte geworfen wird Präzision und Zurück könnten Rundungsfehler verursachen? – Jaan

+0

@Jaan Es ist kein _casting_ noch _rounding_ Problem. Mit 'double x = some_small_double(); if (x/1.0e300) ... 'kann oder darf nicht den' if() 'Pfad nehmen. Das 'x/1.0e300', das mit' double' berechnet wird, ist sicherlich +/- 0.0. 'x/1.0e300', berechnet mit 'long double' math (obwohl die Operanden beide" double "sind) könnte eine von Null verschiedene Zahl sein. – chux

+0

@Jaan "hinzugefügt Null/multipliziert mit eins (was sollte kein Op sein, oder?)" -> Nicht immer. "-0.0" unterscheidet sich vom Hinzufügen von Null. "-0.0 + 0.0" hat normalerweise eine Summe von "+ 0.0". [Manchmal] (https://stackoverflow.com/q/25332133/2410359) ist dieser Unterschied wichtig. Ich _think_ '* 1 'ist normalerweise ein No-Op, aber wenn ein No-Op, warum es Code? – chux