Structures

ComFreek

Mod | @comfreek
Moderator
(Den Beweis bleibe ich schuldig, aber ich denke, man könnte mit der Unendlichnorm argumentieren). Rundungsfehler passieren hier auch nicht, da selbst bei Subtraktionsrundungen der Zähler nur kleiner werden kann, und der Nenner in der Euklidischen Norm keine Subtraktionen aufweist).
Dass das bei exakter Rechnung nicht passieren kann, ist mir klar. (Folgt auch direkt aus dem Wertebereich von cos: R -> R, wenn man die Formel cos(angle(a, b)) = (<a,b>)/(|a||b|) als gegeben nimmt.)

Du hast ein gutes Argument! Doch wie wird |a|, |b| jeweils ausgerechnet? Enthält das Wurzelziehen keine Subtraktionen? Schönes Glatteis :rolleyes:
Wie auch immer man das handhabt, es sollte in der Dokumentation von vec_angle beschrieben werden.
 

cwriter

Erfahrenes Mitglied
Doch wie wird |a|, |b| jeweils ausgerechnet?
Ok, guter Punkt.
Annahme:
C:
double abs(...)
{
double ret = 0.;
for(size_t i = 0; i < dim; ++i)
    ret += vec[i] * vec[i]; //kein pow: Rundungsfehler bei pow!
return sqrt(ret); //sqrt ist eine der exaktesten Funktionen (siehe später)
}
Enthält das Wurzelziehen keine Subtraktionen?
Zumindest keine Cancellation Errors: http://en.cppreference.com/w/c/numeric/math/sqrt
sqrt is required by the IEEE standard to be exact. The only other operations required to be exact are the arithmetic operators and the function fma. After rounding to the return type (using default rounding mode), the result of sqrt is indistinguishable from the infinitely precise result. In other words, the error is less than 0.5 ulp. Other functions, including pow, are not so constrained.
Man hat also einen Fehler von weniger als 0.5 * eps.
In anderen Worten: Der Fehler von sqrt ist irrelevant.
(Schliesslich müsste der Grenzfall x/(x - eps) erreicht werden können, was ja nicht der Fall sein kann, da der Fehler kleiner als 0.5 * eps sein muss und das Supremum von x/x = 1 ist).
D.h. die einzigen Rundungsfehler könnten in den Additionen auftreten, die aber 1) ebenfalls im 0.5 eps-Bereich sein können und 2) durch die Quadrierung eher noch im Zähler als im Nenner auftreten können.

Ich behaupte schlicht einmal, dass es auf Standard (IEEE754)-konformen Systemen keinen Fall geben kann, wo reelle Vektoren in dieser Winkelfunktion für ein NaN im Resultat sorgen können. Ich lasse mich aber gerne widerlegen, ist es interessantes Gebiet.

Im Übrigen halte ich es für sinnfrei, bei Übungsaufgaben überflüssige Checks zu verlangen. (Erinnert mich an meine Prüfungen mit den Aufgaben, per Postcondition eine Addition zu verifizieren (int res = a + b; assert(res == a + b)). Und ja, das war so verlangt).

Gruss
cwriter

/EDIT: Ich bin mir gerade unsicher, wie es bei den Denormalisierten Zahlen aussieht... Allerdings sagt mir meine Intuition, dass es nicht ins Gewicht fällt, da sqrt ja grösser wird.
 
Zuletzt bearbeitet: