DER PROGRAMMIERER
Ein Programmierer sprach einmal
Im vollen Programmierungssaal
(er sagt es lächelnden Gesichts):
"Ich programmiere: Eins durch Nichts".
Jedoch was soll ich weiter schreiben:
Der Programmierer ließ es bleiben.
in memoriam KLEN
In C führt eine Division durch 0 zu einem Programm Abbruch. Ein
Controller stellt dann wohl seine Arbeit ein bis zu einem Neustart.
Du muss im Programm den Teiler selbst auf 0 prüfen und dann die
gewünschten Massnahmen ergreifen.
Nobody schrieb:> In C führt eine Division durch 0 zu einem Programm Abbruch. Ein> Controller stellt dann wohl seine Arbeit ein bis zu einem Neustart.
Wirklich??? Hätte gedacht, dass vielleicht ein Error-Flag gesetzt wird
und das Programm ansonsten "normal" weitergeht...
Ein AVR selbst kann gar nicht dividieren, da sein Befehlssatz keine
Division kennt.
Insofern ist alles, was passiert, abhängig von der Umsetzung des
Hochsprachendivisionsbefehls in den letzlich ausgeführten Maschinencode.
Nobody schrieb:> In C führt eine Division durch 0 zu einem Programm Abbruch. Ein> Controller stellt dann wohl seine Arbeit ein bis zu einem Neustart.
Das kann man nicht so pauschal sagen.
Das Ergebnis ist nicht definiert. Alles mögliche kann passieren,
inklusive einem Prozessorhalt. Aber sehr wahrscheinlich ist das nicht.
Gerade auf einem µC werden die Dinge meistens so gelagert, dass das
Programm zumindest weiter läuft. Je nach Situation hat man dann ein
einmalig falsches Zwischenergebnis (was immer noch fatal ist, nicht
missverstehen), im nächsten Durchlauf durch die Hauptschleife sind dann
aber die Zahlenwerte möglicherweise schon andere, so dass das Programm
ab dann korrekt weiterlaufen kann.
Gerade im Embedded-Bereich ist ein Prozessor-Halt der Super-Gau
schlechthin.
> Du muss im Programm den Teiler selbst auf 0 prüfen
Das auf jeden Fall. Wenn durch 0 dividiert wird, dann deutet das sowieso
meistens auf einen Sonderfall hin, der getrennt behandelt werden muss.
Wissenwollender schrieb:> Stürzt der Controller dann im Betrieb an dieser Stelle ab?
Wie sollte er?
Er hat keinerlei Absturzflags.
Er zieht ganz profan von jedem Bit 0 ab, da es ohne Unterlauf geht.
Das Ergebnis ist folglich 0b1111111111111111 bzw. 0xFFFF.
Wenn Du einen Absturz willst, mußt Du ihn schon selber programmieren:
Häufig genug kriegt man - falls sich die Gleitkomma-Lib an die
ANSI-Vorgaben hält - als Ergebnis eine NAN. Und das ist die größte
Sch*** die es gibt, denn aus einer NAN kommt man anschließend durch nix
mehr heraus. Also auch kein nachträgliches Abfangen im Programm mehr
möglich. Hab ich selber schon oft genug erlebt und mich darüber schwarz
ärgern müssen.
W.S.
W.S. schrieb:> Häufig genug kriegt man - falls sich die Gleitkomma-Lib an die> ANSI-Vorgaben hält - als Ergebnis eine NAN. Und das ist die größte> Sch*** die es gibt, denn aus einer NAN kommt man anschließend durch nix> mehr heraus.
Was ein völlig korrektes Verhalten ist. Nicht nur gemäss ANSI, sondern
auch gemäss einfacher Logik. Operationen auf undefinierte Werte können
nur wiederum undefinierte Werte produzieren.
Allerdings bezieht sich der Thread auf Integer-Rechnung, du aber auf
Fliesskomma-Rechnung.
W.S. schrieb:> Häufig genug kriegt man - falls sich die Gleitkomma-Lib an die> ANSI-Vorgaben hält - als Ergebnis eine NAN. Und das ist die größte> Sch*** die es gibt, denn aus einer NAN kommt man anschließend durch nix> mehr heraus.
Wie meinst du denn "kommt man nicht mehr heraus?". NAN ist doch nur ein
spezieller Wert den eine Variable haben kann. Wieso muss man da irgendwo
raus?
Meist ist es doch auch so, einen Fehler wie Division durch Null will man
nicht wirklich abfangen. Denn was kann man hier denn Bitte noch
ausrichten? Das weist auf einen schweren Fehler in der Programmlogik
hin, meist fehlende Überprüfung von Eingaben, oder schlimmer
irgendwelche Schleifen die zu tief laufen. Also da ist ein sauberes
stehenbeleiben die beste Lösung. Ein "Weiter so", wie im guten alten
Basic mit dem Befehl "On Error Goto Next" behindert nur die Fehlersuche.
Peter Dannegger schrieb:> Er zieht ganz profan von jedem Bit 0 ab, da es ohne Unterlauf geht.> Das Ergebnis ist folglich 0b1111111111111111 bzw. 0xFFFF.
Der Controller schafft sich dann also in seinem Kosmos ein lokales
Unendlich.
cyblord ---- schrieb:> Meist ist es doch auch so, einen Fehler wie Division durch Null will man> nicht wirklich abfangen. Denn was kann man hier denn Bitte noch> ausrichten?
Es gibt Funktionen, die gegen unendlich laufen. z.B., bei 'tan(90°)'
muss es ja trotzdem weitergehen.
Ralf G. schrieb:> cyblord ---- schrieb:>> Meist ist es doch auch so, einen Fehler wie Division durch Null will man>> nicht wirklich abfangen. Denn was kann man hier denn Bitte noch>> ausrichten?>> Es gibt Funktionen, die gegen unendlich laufen. z.B., bei 'tan(90°)'> muss es ja trotzdem weitergehen.
Darum schrieb ich ja "meist".
Warum soviele ironische Antworten?
Die Frage ist absolut berechtigt. Zahlreiche Prozessoren kennen ein
Exception-Handling, bei dem z.B. unterschiedliche Interrupts ausgelöst
werden.
Bei den x86 kompatiblen gibt es einen eigenen Interrupt für Division
durch Null. Weiterhin gibt es dort einen Interrupt für unbekannte
OPcodes. Dieser wurde zu 286 und 386SX Zeiten verwendet, um per
Softwareemulator den 287/387er Koprozessor zu emulieren, der für die
Fliesskommaberechnungen zuständig ist.
Weiterhin gibt es Bibliotheken und Frameworks, die ähnliche Mechanismen
bieten. Wie oben zurecht gesagt:
> Insofern ist alles, was passiert, abhängig von der Umsetzung des> Hochsprachendivisionsbefehls in den letzlich ausgeführten Maschinencode.
Es fehlt jedoch die Aussage, ob in bestimmten Toolchains solche
Mechanismen eingebaut sind.
Gerade als Anfänger in neuen Architekturen geht man von bekannten
Mechanismen aus, und muss sich unterschiedliche Implementierungen und
Herangehensweisen zunächst erarbeiten.
Wissenwollender schrieb:> Der Controller schafft sich dann also in seinem Kosmos ein lokales> Unendlich.
Das übliche Missverständnis. Unendlich ist als Ergebnis genauso richtig
und falsch wie 65535 oder 42. Es kommt halt das raus, was der
Algorithmus der Division erbringt, wenn man den Fall nicht eigens
abfängt.
Tipp des Tages schrieb:> Die Frage ist absolut berechtigt. Zahlreiche Prozessoren kennen ein> Exception-Handling, bei dem z.B. unterschiedliche Interrupts ausgelöst> werden.
Nützt aber alles nix, weil hier nicht nach dem i.d.R. definierten
Verhalten eines Prozessors gefragt wurde, sondern nach dem undefinierten
(nicht: unspezifizierten!) Verhalten von Compiler bzw. dessen Rumtime.
Tipp des Tages schrieb:> Zahlreiche Prozessoren kennen ein Exception-Handling
Ein AVR hat sowas jedoch nicht.
W.S. schrieb:> Häufig genug kriegt man - falls sich die Gleitkomma-Lib an die> ANSI-Vorgaben hält - als Ergebnis eine NAN.
Nein. Man bekommt ein (vorzeichengerechtes) Inf, und das ist völlig
korrekt: wenn man eine von Null verschiedene Zahl durch Null teilt,
kommt nun einmal Unendlich dabei raus. (Dass sich die originale
Frage jedoch auf Ganzzahlen bezog, wurde ja bereits erwähnt.)
Für den simplen (compilezeit-konstanten) Fall wie in obigem Beispiel
wird es sehr wahrscheinlich natürlich der Compiler schon bemerken.
A. K. schrieb:> Jörg Wunsch schrieb:>> Nein. Man bekommt ein (vorzeichengerechtes) Inf, und das ist völlig>> korrekt: wenn man eine von Null verschiedene Zahl durch Null teilt,>> kommt nun einmal Unendlich dabei raus.>> Man kann zwar das praktische Verhalten von Hardware oder Libs so> definieren, mathematisch bleibt es jedoch undefiniert.>
Letzen Endes ist es aber in der Praxis auch ziemlich egal.
Wenn bei einer Division die Möglichkeit besteht, durch 0 zu dividieren,
dann muss dieser Fall gesondert behandelt werden. Und zwar bevor man
dividiert.
Erleichtert wird dieses dadurch, dass eine versuchte Division durch 0
sowieso meistens irgendeinen speziellen Sonderfall darstellt, den ich
sowieso getrennt behandeln möchte. Und dann ist die vorlaufende
Erkennung dieses Sonderfalls normalerweise bei weitem einfacher, als
hinterher ein undefiniertes Divisionsergebnis zu erkennen und zu
bearbeiten.
Karl Heinz schrieb:> als> hinterher ein undefiniertes Divisionsergebnis zu erkennen
Undefiniert steht in der Compiler-Spezifikation, der Prozessor hat im
konkreten Fall natürlich ein definiertes Ergebnis, wenn auch
möglicherweise ein zufälliges. Es kommt aber nicht wirklich drauf an, ob
man sich darauf versteift, dass das Ergebnis der Division undefiniert
ist oder unendlich, weil man so oder so damit nicht weitermachen kann
(der Prozessor kennt auch kein Unendlich). Genausowenig hilft die
Darstellung NAN, die es bei real gibt, das bringt einen auch nicht
weiter als eine Exception.
Da ist ganz einfach der Programmierer gefragt, was geschehen soll.
Georg
Die Frage ist wirklich ernst gemeint:
Läßt sich das ein "C"-Kompiler gefallen, wenn man ihm einen Quelltext
gibt, der eine Division durch Null erzeugt?
(Ich kann es nicht probieren, weil ich hier keinen derartigen Kram
auf dem Rechner habe und ihn auch nicht installieren könnte bzw. dürfte)
MfG Paul
Paul Baumann schrieb:> Die Frage ist wirklich ernst gemeint:> Läßt sich das ein "C"-Kompiler gefallen, wenn man ihm einen Quelltext> gibt, der eine Division durch Null erzeugt?
Was ein ordentlicher Compiler ist, wird im Zuge der Constant-Folding
Optimierung drauf kommen, dass hier durch 0 dividiert wird und eine
entsprechende Warnung rausgeben.
Verpflichtet dazu ist er, wie bei allen Warnungen, allerdings nicht.
Im C-Standard gibt es keine Warnungen. Im C Standard steht nur, was ein
Error ist und was nicht. Warnungen sind freiwillige Serviceleistungen
des Compilers.
Paul Baumann schrieb:> Läßt sich das ein "C"-Kompiler gefallen, wenn man ihm einen Quelltext> gibt, der eine Division durch Null erzeugt?
GCC gibt eine Warnung. Wenn er es merkt.
Paul Baumann schrieb:> Läßt sich das ein "C"-Kompiler gefallen
Naja, nehmen wirs mal ernst: was verstehst du unter "gefallen lassen"?
Wenn er es merkt übersetzt er das Programm nicht oder gibt wenigstens
eine Warnung aus - das kann man einstellen, man hat also in der Hand,
was er sich gefallen lässt. Es macht aber wenig Sinn, alle Fehler und
Warnungen abzustellen, da kommt keine brauchbare Software raus.
Georg
Paul Baumann schrieb:> Die Frage ist wirklich ernst gemeint:> Läßt sich das ein "C"-Kompiler gefallen, wenn man ihm einen Quelltext> gibt, der eine Division durch Null erzeugt?
Ja.
Wenn er schlau ist, kann er vieleicht eine Warnung ausgeben, aber
prinzipiel geht es ihn nix an, wenn du so etwas machst.
Tipp des Tages schrieb:> Die Frage ist absolut berechtigt. Zahlreiche Prozessoren kennen ein> Exception-Handling, bei dem z.B. unterschiedliche Interrupts ausgelöst> werden.> Bei den x86 kompatiblen gibt es einen eigenen Interrupt für Division> durch Null.
Diese Prozessoren können dividieren. Ein AVR aber kann das nicht.
Verwechsle nicht Hochsprache mit den vom Prozessor ausgeführten
Maschinenbefehlen - bei einem Prozessor, der keine Division kennt, ist
eine Exception (oder ein Software-Interrupt) für einen Divisionsfehler
ziemlich ... nutzlos.
Georg schrieb:> Karl Heinz schrieb:>> als>> hinterher ein undefiniertes Divisionsergebnis zu erkennen>> Undefiniert steht in der Compiler-Spezifikation, der Prozessor hat im> konkreten Fall natürlich ein definiertes Ergebnis
Frage nicht gelesen? Ein AVR hat keinen Divisionsbefehl. Eine Division,
ganz egal ob Ganzzahl oder Fließkomma wird immer von einer Biblio-
theksfunktion ausgeführt. Und deren Verhalten ist zwar sicher für eine
spezifische Toolchain vorhersagbar, im Allgemeinen jedoch undefiniert.
> wenn auch möglicherweise ein zufälliges.Das nun ganz sicher nicht. Computer funktionieren deterministisch.
> Genausowenig hilft die> Darstellung NAN, die es bei real gibt, das bringt einen auch nicht> weiter als eine Exception.
Der Punkt ist, daß C für Arithmetik keine Exceptions vorsieht. Weder für
Division durch Null noch (was sehr nützlich wäre) für einen Überlauf.
Und weil es keine out of band Signalisierung gibt, hat man die NaN
Pseudowerte eingeführt, um wenigstens in band signaling zu haben. Weil
man dafür aber den Wertebereich des Ergebnisses einschränken muß hat man
es nur für Fließkommazahlen gemacht, weil es da ohnehin schon ungültige
interne Darstellungen gibt, von denen man einfach ein paar passend
umdefiniert hat.
Langer Rede kurzer Sinn: das NaN Ergebnis ist die Exception.
XL
Danke für die Antworten auf meine Frage. Es stellt sich aber gleich
noch eine: Wenn ich den Text von Axel richtig verstanden habe, dann
gibt es auch da keine Fehlermeldung, wenn ich z.B. 2 Byte miteinander
multipliziere und das Ergebnis aus Versehen oder Unachtsamkeit auch
in eine Bytevariable hineinwürgen will?
Wenn das so ist, will ich kein "C" haben.
MfG Paul
Axel Schwenke schrieb:> Das nun ganz sicher nicht. Computer funktionieren deterministisch.
Wie würdest du denn den Inhalt nicht initialisierter Variablen
bezeichnen? Klar arbeitet ein Prozessor deterministisch, aber für den
Programmierer ist der Inhalt nicht vorhersehbar. Man kann ja auch
behaupten, die Brownsche Molekularbewegung sei in Wirklichkeit
deterministisch, bloss hilft das überhaupt nicht weiter.
Georg
Paul Baumann schrieb:> Wenn das so ist, will ich kein "C" haben.
C ist eben nichts für Leute, die die Tante brauchen um Lulu zu gehen.
Dein heiss geliebtes BASCOM hat auch so seine Probleme.
Karl Heinz schimpfte:
>C ist eben nichts für Leute, die die Tante brauchen um Lulu zu gehen.
War Dir das Mittagessen zu heiß?
>Dein heiss geliebtes BASCOM hat auch so seine Probleme.
Das habe ich mit keinem Wort behauptet. Was hier los ist....
:-(
Paul
Irgendwie geht hier etwas durcheinander.
Nämlich das Verhalten eines Atmel und "C".
1. Soweit mir bekannt juckt es einen AVR kein bisschen, wenn der
durch Nix teilen soll.
2. Vor längerer Zeit habe ich mal eine 16-Bit Division aus den AVR-
Bibliotheken extrahiert. Da war keine explizite Abfrage auf null.
3. NaN kenne ich nur im Zusammenhang mit Fließkommazahlen bzw.
-bibliotheken. Darum ging’s hier aber nicht. Das Verhalten hier
hängt wohl vom Compiler bzw. davon ab, ob man C oder C++ verwendet.
Paul Baumann schrieb:>>Dein heiss geliebtes BASCOM hat auch so seine Probleme.>> Das habe ich mit keinem Wort behauptet. Was hier los ist....
Vielleicht kannst du dir vorstellen, das mit dieses dauernde C-Bashing
mitlerweile schon ganz gehörig auf den Sack geht? Zumal viele derartige
'Untergriffe' immer wieder von Leuten kommen, die C überhaupt nicht
ausreichend beherrschen um sich hier ein Urteil erlauben zu können.
Ausserdem behauptet auch niemand, dass C das Beste seit geschnittenem
Brot wäre. Alle C Programmierer sind sich bewusst, dass die Sprache ihre
Problemkreise hat (die meistens dann auch gar nicht in den Bereichen
angesiedelt sind, die immer wieder gerne von "C-Laien" kritisiert
werden)
Amateur schrieb:> 1. Soweit mir bekannt juckt es einen AVR kein bisschen, wenn der> durch Nix teilen soll.
Es kann ihn ja auch nicht jucken. Er hat schlicht keinen
Divisionsbefehl. Also wird er niemals dividieren.
Die Division wird lediglich durch den Compiler nachgebildet, und genau
darum dreht sich die Diskussion in letzter Zeit. Nicht um den AVR.
Karl Heinz schrie:
>Vielleicht kannst du dir vorstellen, das mit dieses dauernde C-Bashing>mitlerweile schon ganz gehörig auf den Sack geht?
Ich habe mir nur erlaubt, 2 Fragen zu stellen -nicht mehr.
>Zumal viele derartige>'Untergriffe' immer wieder von Leuten kommen, die C überhaupt nicht>ausreichend beherrschen um sich hier ein Urteil erlauben zu können.
Ich beherrsche C nicht nur nicht ausreichend, sondern überhaupt nicht
Das war auch der Grund für meine Fragen, die ich anderenfalls gar nicht
hätte stellen müssen.
Im Übrigen ist auch nicht die Pflicht eines Moderators, auf jeden
Artikel zu antworten, dessen Inhalt nicht seinen Gefallen findet!
Paul
Paul Baumann schrieb:> Ich habe mir nur erlaubt, 2 Fragen zu stellen -nicht mehr.
Nimms nicht persoenlich - Nein, du fragst nicht sachlich, sondern
abwertend - das fiel auch mir auf.
Du musst ja kein C nutzen, aber in einem Thread wie diesem ist
irrelevant, was du von C haeltst...
Paul Baumann schrieb:> Ich habe mir nur erlaubt, 2 Fragen zu stellen -nicht mehr.
Nö, Paul:
Paul Baumann schrieb:> Wenn das so ist, will ich kein "C" haben.Das war das, was Karl Heinz „auf die Palme“ gebracht hat und was
er als „C-Bashing“ bezeichnet.
Axel Schwenke schrieb:> Und weil es keine out of band Signalisierung gibt, hat man die NaN> Pseudowerte eingeführt, um wenigstens in band signaling zu haben.
Die Entwicklung von IEEE 754 hat nichts mit C zu tun. In den 70ern gab
es ein Sammelsurium verschiedener Fliesskommaformate, jeder Hersteller
hatte eigene. C hingegen kannte damals kaum jemand. Dass man sich in
diesem Rahmen auch um Grenzverhalten und unzulässige Operationen kümmert
ist nur konsequent. Wobei IEEE 754 seinerseits abschaltbare Exceptions
vorsieht.
Die Sprache C andererseits verlangt bis heute nicht die Konformität zu
IEEE 754 bzw. IEC 60559 und definiert auch kein bestimmtes Verhalten bei
sigalling NaNs. Das sind einfach zwei verschiedene Paar Stiefel,
entspricht es doch dem Leitmotiv, möglichst wenig Plattformspezifika in
die Sprache hinein zu definieren.
Georg schrieb:> Axel Schwenke schrieb:>> Das nun ganz sicher nicht. Computer funktionieren deterministisch.>> Wie würdest du denn den Inhalt nicht initialisierter Variablen> bezeichnen? Klar arbeitet ein Prozessor deterministisch, aber für den> Programmierer ist der Inhalt nicht vorhersehbar.
Und was läßt dich glauben, eine Divisionsroutine würde bei einer
Division durch Null einfach den Inhalt einer nicht initialisierten
Variablen zurückgeben?
Mal abgesehen davon, daß ein solches Verhalten vom Standard gedeckt
wäre: ich würde eine solche Laufzeitbibliothek mit maximaler Skepsis
betrachten.
XL
Helge schrieb:> Mein Arduino sagt:
...was auch immer der Compiler zur Übersetzungszeit da reinschreibt.
Viel interessanter ist der nicht konstante Fall, also was zur
Laufzeit wirklich dann ausgerechnet wird.
Aber da es sich um undefiniertes Verhalten handelt, kann das — selbst
wenn man heute ein bestimmtes, nachvollziehbares Verhalten
feststellen kann — schon übermorgen ganz anders aussehen.
Der einzig korrekte Weg kann also nur sein, dass man den Divisor vor
der Division gegen 0 testet und dann seine eigene Ausnahmebehandlung
implementiert.
Jörg Wunsch schrieb:> Helge schrieb:>> Mein Arduino sagt:>> ...was auch immer der Compiler zur Übersetzungszeit da reinschreibt.
Nur schade dass der normale Arduino User absolut keine Vorstellung
dieser zusammenhänge hat. Compiler, Linker, Präprozessor, Laufzeit alles
ein dichter Nebel an Worthülsen der die Insel der Verzweiflung umweht.
Paul Baumann schrieb:> Wenn ich den Text von Axel richtig verstanden habe, dann> gibt es auch da keine Fehlermeldung, wenn ich z.B. 2 Byte miteinander> multipliziere und das Ergebnis aus Versehen oder Unachtsamkeit auch> in eine Bytevariable hineinwürgen will?
So ist es. C abstrahiert Register und ALU einer CPU zu Variablen und
arithmetischen/logischen Operatoren. Leider fällt bei dieser Abstraktion
auch das Flagregister der ALU mit hinten runter. Es wäre in vielen
Fällen enorm hilfreich, die Flags auch auf Hochsprachenebene zur
Verfügung zu haben.
Die kanonische Lösung besteht darin, die Rechnung immer mit dem nächst-
größeren Typ zu machen (bzw. allgemein einem Typ bei dem man sicher ist,
daß er das Ergebnis in jedem Fall halten kann). Was natürlich immer dann
zum Problem wird, wenn man Rechnungen mit dem längsten verfügbaren Typ
macht.
> Wenn das so ist, will ich kein "C" haben.
Bei anderen Programmiersprachen bist du da auch nicht besser aufgehoben.
Im Prinzip könnte man auch die C Laufzeitbibliothek so auslegen, daß sie
in solchen Fällen einen Laufzeitfehler auslöst (wie es z.B. Turbopascal
macht). Man macht es aber nicht, weil es den Code für den Normalfall
(kein Überlauf) langsamer machen würde. Und auch weil nicht abfangbare
Exceptions bäh sind. Gerade bei einem µC sollte das einleuchten.
XL
Axel Schwenke schrieb:> Mal abgesehen davon, daß ein solches Verhalten vom Standard gedeckt> wäre: ich würde eine solche Laufzeitbibliothek mit maximaler Skepsis> betrachten.
In der PowerPC Spezifikation ist der Inhalt des Zielregisters bei einer
ganzzahligen Division durch 0 undefiniert. Eine Exception ist damit
nicht verbunden, jedenfalls nicht im Divisionsbefehl selbst.
Es kann also durchaus sein, dass das Zielregister in diesem Fall nicht
verändert wird. Wenn in diesem Register vorher eine echte Zufallszahl
drin stand, dann hast du deine Division durch 0 mit echt zufälligem
Ergebnis.
Spass am Rande: Aus der Systematik der PowerPC Befehle ergeben sich
Varianten von Divisionbefehlen, bei denen im Fall einer Division durch 0
weder eine Exception noch irgendein anderes definiertes Ergebnis
vorliegt, auch keine Flags. Also schlicht nichts definiert ist.
@Axel
Danke für Deine Antwort.
Karl-Heinz schrub:
>Dein heiss geliebtes BASCOM hat auch so seine Probleme.
Richtig. Als Beweis dafür hänge ich ein Bild an, aus dem hervorgeht,
daß eine Division durch Null zum Ergebnis 255 führt, wenn das Ergebnis
als Byte dimensioniert ist. Als Single kommt Null heraus. Auch der
Bascom-
kompiler läßt sich also so einen Unfug gefallen.
>> Wenn das so ist, will ich kein "C" haben.
Jörg schrabte:
>Das war das, was Karl Heinz „auf die Palme“ gebracht hat und was>er als „C-Bashing“ bezeichnet.
Gut, dann muß ich im Forum "Markt" eine Annonce aufgeben, daß ich nach
einer Goldwaage suche, auf die ich meine Worte legen kann...
;-)
MfG Paul
Paul Baumann schrieb:> Gut, dann muß ich im Forum "Markt" eine Annonce aufgeben, daß ich nach> einer Goldwaage suche, auf die ich meine Worte legen kann...
Eine Laborwaage tut's auch. Wenn du keine hast, bei mir im Keller
steht eine, schick die Worte einfach vorher zu mir, ich leg' sie
dann mal drauf. ;-)
Paul Baumann schrieb:> Danke für die Antworten auf meine Frage. Es stellt sich aber gleich> noch eine: Wenn ich den Text von Axel richtig verstanden habe, dann> gibt es auch da keine Fehlermeldung, wenn ich z.B. 2 Byte miteinander> multipliziere und das Ergebnis aus Versehen oder Unachtsamkeit auch> in eine Bytevariable hineinwürgen will?
Nein, natürlich nicht. Könnte ja auch passen, Z.B. 1*1=1 paßt.
> Wenn das so ist, will ich kein "C" haben.
Das will man sowieso nicht. Allerdings hat das ganz andere Gründe.
Numerische Überläufe ggf. auch ignorieren zu können, ist jedenfalls eine
Eigenschaft einer Programmiersprache, die sowohl extrem nützlich als
auch hochgefährlich sein kann. Wenn du das noch nicht begriffen hast,
bist du ein Lamer, der sich aus solchen Diskussionen einfach mal
raushalten sollte.
So einfach ist das.
Was passieren kann wurde ja bereits gesagt, wobei sich das auf
int-Division bezieht:
A. K. schrieb:> C definiert eine Division durch 0 als "undefiniert".
Konkret:
>> C99 3.4.3 undefined behavior>>>> behavior, upon use of a nonportable or erroneous program>> construct or of erroneous data, for which this International>> Standard imposes no requirements.>>>> NOTE>>>> Possible undefined behavior ranges from ignoring the>> situation completely with unpredictable results, to behaving>> during translation or program execution in a documented>> manner characteristic of the environment (with or without>> the issuance of a diagnostic message), to terminating a>> translation or execution (with the issuance of a diagnostic>> message).
Helge schrieb:> Mein Arduino sagt:>> Was ist 1/0 ? Es ist -1
Und wer hat da jetzt gerechnet?
War das der Compiler auf dem PC, der richtig erkannt hat, dass er die
ganze Rechnung wegoptimieren kann und nur eine Konstante ausgeben muss,
oder war das der AVR, der wirklich zwei Zahlen durch einen Algorithmus
gejagt hat, den man im Quellcode mit "/" kennzeichnet?
Da sollte man erstmal in den lst-File gucken, was der AVR zu dem
Ergebnis beigetragen hat.
C-Hater erklärte großspurig:
>Numerische Überläufe ggf. auch ignorieren zu können, ist jedenfalls eine>Eigenschaft einer Programmiersprache, die sowohl extrem nützlich als>auch hochgefährlich sein kann. Wenn du das noch nicht begriffen hast,>bist du ein Lamer, der sich aus solchen Diskussionen einfach mal>raushalten sollte.
Nein, ich habe noch nicht begriffen, wozu das nützlich sein könnte.
Aber Du kannst es ja mal kurz und prägnant erklären. Schließlich
will ich ja kein Lamer sein, es reicht mir, mit verstauchtem Fuß
ein Lahmer zu sein.
SCNR
Paul
Helge schrieb:> Das sollte Jörg beantworten können, er ist am nächsten drann beim> Compilerbau.
Nö, Johann. Hat sich ja schon ausreichend zu Wort gemeldet hier.
Das "Ergebnis" kommt von den __[u]divmod{q,h,ps,s,d}i4 Routinen der
libgcc, die im Falle von avr-gcc in Assembler implementiert sind.
AFAIR liefern diese bei einem Divisor von 0 einen Quotienten, bei dem
alle Bits gesetzt sind. Für den Rest kann es jeder bei Interesse selbst
nachvollziehen:
http://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/avr/lib1funcs.S?content-type=text%2Fplain&view=co
Für die nicht zwingend saturierenden Fixed-Point Divisionen sind m.W.
ebenfalls so, daß diese auf den Maximal- bzw. Minimal-Wert hin
Saturieren.
Helge schrieb:> Das sollte Jörg beantworten können, er ist am nächsten drann beim> Compilerbau.
Dafür brauchts keinen Compilerbau. Testcode übersetzen und reinsehen
reicht. Ich selber würde es allerdings auch nicht dem Compiler, sondern
der Runtime überlassen, damit sich ein konsistentes Verhalten ergibt,
auch wenn das von der Sprache selbst nicht gefordert wird.
Jörg Wunsch schrieb:> Der einzig korrekte Weg kann also nur sein, dass man den Divisor vor> der Division gegen 0 testet und dann seine eigene Ausnahmebehandlung> implementiert.
Jörg, manchmal regst du mich auf. Eine NAN kriegt man auch bei
Überläufen - und die gibt's dann AUCH, wenn der Divisor ungleich Null
ist. Das Ergebnis braucht bloß zu groß zu sein. Wenn du (wie ich) massiv
mit Meßwerten zu tun hast, wo Kunden irgendwo ihre Anlagen falsch
einjustieren und dann sowas wie 1.234E+30/1.234E-33 zuwege bringen, dann
klemmt es OHNE daß man als Programmierer viel dagegen tun kann, außer
sowas wie if (fabs(x)<1E-29)...
Weitaus besser wäre es, wenn bei all den saubescheuerten Gleitkomma-Libs
genau SO verfahren worden wäre wie in der digitalen Signalverarbeitung,
wo Übersteuerungen (die immer mal vorkommen) einfach durch sättigendes
Verhalten abgefangen werden. Wenn dann mal 123/0 vorkommt, dann gibt das
eben 7FFFFFFFh und fertig. Respektive -123/0 --> 80000000h
Man macht bei sowas keinen wirklich relevanten Fehler und spart sich ne
Menge Telefonate.
W.S.
W.S. schrieb:> Jörg, manchmal regst du mich auf. Eine NAN kriegt man auch bei> Überläufen
Du uns auch: in diesem Thread geht es um ganzzahlige Divisionen,
und da brauchen wir über NaNs nicht weiter zu diskutieren.
Wenn du über Sinn und Unsinn von IEEE754 diskutieren willst, dann
öffne bitte einen eigenen Thread.
W.S. schrieb:> Weitaus besser wäre es, wenn bei all den saubescheuerten Gleitkomma-Libs> genau SO verfahren worden wäre wie in der digitalen Signalverarbeitung,
Du bringst hier ein Beispiel, in dem saturierende Arithmetik sinnvoll
ist. Es gibt andere, wo es geradezu kriminell leichtsinnig wäre,
sinnvolle Ergebnisse vorzutäuschen, wo doch zur Laufzeit bereits bekannt
ist, dass sie kompletter Unsinn sind.
Leb damit, oder such dir eine Laufzeit oder Hardware, die deinen
Wünschen entsprechend arbeitet. Wenn solches Verhalten bei DSPs wirklich
bedeutend ist, dann sollte es welche geben, die sich entsprechend
verhalten. Die Sprache C lässt das zu, sie verlangt nicht nach IEEE 754.
@Paul
Mein C-Compiler(CVAVR) erkennt, wenn Multiplikationen oder Additionen
möglicherweise zu Überläufen der Zielvarable führen ebenso erkennt er
möglche Unterläufe und mögliche Nulldivisionen.
Das alles meldet er während der Compilation. Ich habe dann die
Möglichkeit dies zu ignorieren oder abzufangen.
Meist habe ich die Varablen dann double oder long oder longlong
definiert bzw. wenn der Definitonsbereich klar war und die
Überschreitung nur theoretisch aber nicht real möglich war die Warnung
ignoriert.
Bis jetzt hatte ich damit nie ein Problem.
Simon S. schrieb:> Ich hatte das vor langem mal ausprobiert
Trotzdem nochmal: das ist nicht garantiert, und kann und darf sich
bereits mit der nächsten Version von Compiler oder Bibliothek ändern.
@Wilfried
Danke für Deine vernünftige Antwort. Das hat manch Einer hier nicht
drauf, einfach nur eine Frage zu beantworten, ohne eine Axt
hinterherzuwerfen.
;-)
MfG Paul
Route66 schrub:
>Er heißt Winfried!
Das kommt davon, daß mein Kollege Wilfried heißt. Grmmlhmpf!
;-)
>Brille? - Wenigfrau!
Wenigfrau?
:-)))
Wunderbar!
Kannst Du mal meine Brille beschlagen? Ach, das wird mir jetzt ein
bisschen
fiel, Mann!
MfG Paul
Paul Baumann schrieb:> Wenigfrau?
Eigentlich müsste es "Venigfrau" heissen.
> Kannst Du mal meine Brille beschlagen?
Gestell kaputt? Hufeisen vorm Kopp sehen aber ziemlich doof aus.
[NEBENBEI]
Paul Baumann schrieb:> Wenn das so ist, will ich kein "C" haben.
Wer das nicht versteht, wenn's von Paul kommt, den verstehe ich nicht!
[/NEBENBEI]
@Paul
Vom Compiler zu verlangen, dass er sich um 'Division durch null' oder
'tan(90°)' kümmert, ist einfach Unsinn (sag ich jetzt mal so).
Sicher ist das kein Problem, sowas zu integrieren, aber das schleppt man
dann in jedem Programm mit rum! Jeden Sonderfall! Alles! Und das
Ergebnis? Ist einfach falsch:
W.S. schrieb:> Wenn dann mal 123/0 vorkommt, dann gibt das> eben 7FFFFFFFh und fertig. Respektive -123/0 --> 80000000h
In vielen Fällen wird die Genauigkeit reichen. Aber mathematisch exakt
ist das nicht. Wem das reicht, der setzt das in seinem Programm einfach
selbst so um.
Denn es geht in der Hauptanwendung von 'C' nicht um ein paar
LED-Basteleien ;-)
Paul Baumann schrieb:> Wenn ich den Text von Axel richtig verstanden habe, dann> gibt es auch da keine Fehlermeldung, wenn ich z.B. 2 Byte miteinander> multipliziere und das Ergebnis aus Versehen oder Unachtsamkeit auch> in eine Bytevariable hineinwürgen will?
Genau aus dem gleichen Grund, wie oben. Vorher (kurz) überlegen, und
dann nimmt man den richtigen Wertebereich.
Ralf schrub:
>Vorher (kurz) überlegen, und dann nimmt man den richtigen Wertebereich.
Ja, ist ja richtig. Nur: Wem das noch nicht passiert ist, das falsche
Format für seine Ausgabe zu erwischen, der werfe mit dem ersten Trafo!
;-)
MfG Paul
Paul Baumann schrieb:> Nur: Wem das noch nicht passiert ist, das falsche> Format für seine Ausgabe zu erwischen,
Das kommt sicher vor! "C" ist eben nicht für uns Bastler gedacht. Wir
verwenden es nur. Aber wer da ernsthaft damit arbeitet (auch
hobbymäßig), der schätzt den daraus resultierenden schlanken Code.
(In jedem Beruf gibt's Stolperfallen!)