Forum: Compiler & IDEs Division durch Null


von Walter T. (nicolas)


Lesenswert?

Guten Abend,
heute hat mich die Werbebroschüre für ein Werkzeug zur statischen 
Codeanalyse erreicht. Dabei wurde angespriesen, daß beispielsweise die 
folgende problematische Codestelle gefunden würde:
1
void foo (int* depth)
2
{
3
  float advance;
4
  *depth = *depth + 1;
5
  advance = 1.0/(float)(*depth);
6
  if (*depth < 50)
7
    foo (depth);
8
}
9
10
void bug _ in _ recursive ()
11
{
12
  int x;
13
  if (random _ int())
14
  {
15
    x = -4;
16
    foo ( &x );
17
  }
18
  else
19
  {
20
    x = 10;
21
    foo ( &x );
22
  }
23
}
(ich gehe mal davon aus, daß der Codeschnipsel zu kurz ist, um 
Umheberrechte zu haben).

Hier wird die unter Umständen entstehende Division float durch float 0 
als Fehler gefunden.

Bislang war ich davon ausgegangen, daß float nach IEEE 754 definiert 
ist, wo eine Division durch Null -Inf oder Inf liefert - also mitnichten 
eine problematische Operation ist, sondern ganz solide eine Meldung 
liefert, (wobei man das ja üblicherweise als Indiz nutzt, daß etwas 
numerisch aus dem Ruder läuft).

Deswegen die Frage an die GCC-Fraktion (GCC, ARM-GCC, AVR-GCC): Ist die 
Division durch float Null problematisch? Undefiniert? Ist ein float hier 
gar nicht nach IEEE 754 definiert?

Irgendwie finde ich, wenn ich nach diesem Thema suche nur Bugreports.

Viele Grüße
W.T.

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

Walter Tarpan schrieb:
> Ist die
> Division durch float Null problematisch? Undefiniert? Ist ein float hier
> gar nicht nach IEEE 754 definiert?
Undefiniert. Am PC gibts eventuell SIGFPE, am ARM eventuell eine 
Floating Point Exception... Wie auch immer, es kommt sicherlich nichts 
"sinnvolles" raus, und der Programmierer wollte sicherlich nicht durch 0 
teilen - das Programm macht also irgendwas "komisches" - und das ist 
noch viel schlimmer als ein Absturz, weil man es nicht bemerkt! - und 
das programm dann eine Maschine falsch steuert oder was auch immer.

von Amateur (Gast)


Lesenswert?

Mag ja sein, dass das Ganze ein philosophisches Problem ist, aber in dem 
Fall, in dem eine Division durch Irgendwas vorkommt, so MUSS auch eine 
Division durch Null möglich sein.
Natürlich ist in diesem Falle eine Sonderbehandlung nötig, aber nicht 
immer lässt sich ein Problem mit: if (Divisor < 0.01) Spielverderber; 
lösen.
Gerade wenn's mal wieder rund (Kreis) geht, kann das Ergebnis auch 
sinnvoll sein.

von Walter T. (nicolas)


Lesenswert?

Amateur schrieb:
> Mag ja sein, dass das Ganze ein philosophisches Problem ist,

Das Ganze ist kein philosophisches Problem. Es gibt nach IEEE 754 eine 
definierte Behandlung der Division durch 0.0FL, bei der -Inf oder Inf 
herauskommt, je nach dem welches Vorzeichen der Zähler und die Null 
haben.

Die "BLAS" und die "LAPACK"-Libraries haben das auch genau so 
implementiert. Mit anderen Numerik-Libraries habe ich noch nie 
gearbeitet.

Aber offensichtlich scheint dieses Verhalten eine Eigenschaft dieser 
Libraries und nicht des "float"- oder "double"-Datentyps, also nicht 
selbstverständlich zu sein.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Amateur schrieb:
> Mag ja sein, dass das Ganze ein philosophisches Problem ist

Nö.
Eine Division durch 0 ist ein ganz handfestes Problem.
Sie bedeutet, dass du in der Herleitung deiner Mathe irgendetwas 
übersehen hast.

> , aber in dem
> Fall, in dem eine Division durch Irgendwas vorkommt, so MUSS auch eine
> Division durch Null möglich sein.

Müssen tut nur das, was im C-Standard steht.
Und da steht nichts davon, dass eine Division durch 0 zulässig ist.

> Natürlich ist in diesem Falle eine Sonderbehandlung nötig, aber nicht
> immer lässt sich ein Problem mit: if (Divisor < 0.01) Spielverderber;
> lösen.

Doch. Das lässt sich immer so lösen.
Wenn du durch 0 dividierst, dann hast du ein Problem. Punkt.

> Gerade wenn's mal wieder rund (Kreis) geht, kann das Ergebnis auch
> sinnvoll sein.

Wie soll da irgendwas sinnvoll sein? Was dividierst du 'an einem Kreis', 
so dass eine Division durch 0 eine sinnvolle Operation ist? Wenn du je 
in der Geometrie auf eine derartige Situation stösst, dann machst du 
etwas ganz grundsätzlich falsch, bzw. hast etwas ganz grauslich 
übersehen. Und nein, auch ein Tangens von 90° rettet dich da jetzt 
nicht.

von Walter T. (nicolas)


Lesenswert?

Karl Heinz schrieb:
> Wenn du je
> in der Geometrie auf eine derartige Situation stösst, dann machst du
> etwas ganz grundsätzlich falsch, bzw. hast etwas ganz grauslich
> übersehen.

Daß ich mal einer Aussage von Dir im Bereich der Programmierung vehement 
widersprechen würde, hätte ich nie gedacht. Aber in diesem Fall scheint 
Dir der Nutzen vermutlich einfach noch nie begegnet zu sein.

Wenn man mit großen Gleichungssystemen (Matrizes) hantiert, ist leider 
manchmal das Phänomen eines schleichenden Rangabfalls zu beobachten, 
d.h. im Rahmen der Operationen werden die Zeilen der Matrix linear immer 
abhängiger. (Wir reden hier nicht über Computergrafik- da kann man 
Matrizes meist orthogonalisieren oder sogar orthonormalisieren.) Das ist 
insbesondere bei sehr steifen Systemen (d.h. Systeme, bei denen die 
Eigenwerte sehr unterschiedliche Größenordnungen haben) der Fall.

Hier ist es sinnvoll, die Operationen einfach zuzulassen - Ergebnis sind 
dann Vektoren oder Matrizes, bei denen einige Stellen mit Inf oder NaN 
markiert sind - und den aufgetretenen Problemen auf einer höheren Ebene 
zu begegnen. Oft sind auch -selbst wenn Teile der Zerlegung durch NaNs 
unbrauchbar geworden sind- die restlichen Teile brauchbar. 
Beispielsweise dann, wenn man nur an den größten/kleinsten oder 
mittleren Eigenwerten oder -Vektoren interessiert ist. Oder aber es wird 
anhand der Struktur des Ergebnisses (inklusive der durch NaNs markierten 
Elemente) eine Reparametrierung ausgeführt, um im nächsten 
Iterationsschritt besser dazustehen.

Differentialgeometrie ist ja auch Geometrie, gelle?

Das findet natürlich nicht auf einem AVR und auch nicht auf einem ARM 
statt. Und statt C ist da eher Fortran verbreitet. Aber Seltenheitswert 
hat es deshalb nicht.

Viele Grüße
W.T.

P.S.: Das ist der Bereich, wo ich mich wohler fühle. Deswegen stelle ich 
ja auch immer so blöde Fragen zum AVR :-)

: Bearbeitet durch User
von Jasch (Gast)


Lesenswert?

Walter Tarpan schrieb:
[...]
> Bislang war ich davon ausgegangen, daß float nach IEEE 754 definiert
> ist, wo eine Division durch Null -Inf oder Inf liefert - also mitnichten

Jein. Wenn Du das in Assembler tust und die zuständigen Flags im 
benutzten Prozessor entsprechend gesetzt hast...

> eine problematische Operation ist,

Division durch 0 unproblematisch? Noch nie sowas gehört...

> Deswegen die Frage an die GCC-Fraktion (GCC, ARM-GCC, AVR-GCC): Ist die
> Division durch float Null problematisch? Undefiniert?

Undefiniert, sagt ISO/IEC 9899:1999 (aka ANSI C99) 6.5.5. Absatz 5.

> Ist ein float hier gar nicht nach IEEE 754 definiert?

Nicht notwendigerweise, wahrscheinlich nur wenn die Hardware IEC 
60559:1989 (vorher auch mal ANSI/IEEE 754−1985 genannt) kann und in 
jedem Fall nur wenn die C-Implementation anzeigt dass sie das so tut.

Dazu steht eine Menge Zeugs im (normativen) Anhang F. Es duerfte oft das 
Aendern von Compilerflags/Runtime-Konfiguration involvieren soweit ich 
mich erinnere.

Natuerlich kann der aktuelle C-Standard wieder andere Dinge sagen...

von Walter T. (nicolas)


Lesenswert?

Sieh an. Ich bin beim K&R heute endlich bis Seite 193 gekommen und da 
steht:

"Die Behandlung von [...] Division durch Null [...] ist in der Sprache 
nicht definiert. [...] Die Behandlung von Division durch Null und allen 
Ausnahmen bei Gleitpunktrechnung variiert zwischen verschiedenen 
Implementierungen; manchmal kann sie durch nicht-standardisierte 
Bibliotheksfunktionen beeinflußt werden."

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.