Exception divide by 0

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

 

sinjin

Betreff: Exception divide by 0

BeitragSa, Feb 22, 2020 22:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich kenne Exceptions nur noch von DOS, da war es relativ simple die abzufangen und mein eigenes Ergebnis einzutragen (in Assembler). Nun die Frage. wenn ich sowas mache wie:
Code: [AUSKLAPPEN]
local a%=0
print 15/a

Wie mache ich es das 0 rauskommt (oder halt ne Zahl die ich haben will), ohne Exception bzw mit Exception aber meine eigene? Halt ohne Fehlermeldung...Ganz ehrlich? #NAN und unendlich finde ich Quark als Ergebnis, ich will dann schlicht Null haben.

Rallimen

Sieger des 30-EUR-Wettbewerbs

BeitragSa, Feb 22, 2020 23:29
Antworten mit Zitat
Benutzer-Profile anzeigen
meine Idee wäre so....
dann gibt es kein Runtimeerror

Code: [AUSKLAPPEN]
Id a=0 then
Print 0
else
Print 15/a
endif
[BB2D | BB3D | BB+]
 

sinjin

BeitragSo, Feb 23, 2020 2:36
Antworten mit Zitat
Benutzer-Profile anzeigen
ich will ja das der Assembler mir DIREKT das Ergebnis sagt... deine Methode wäre zu einfach und ich will meinen Code nicht voller IF THEN haben, ich will sofort 0 haben. Das macht ja schliesslich eine Exception!

Holzchopf

Meisterpacker

BeitragSo, Feb 23, 2020 11:55
Antworten mit Zitat
Benutzer-Profile anzeigen
sinjin hat Folgendes geschrieben:
ich will sofort 0 haben. Das macht ja schliesslich eine Exception!

Ähh... Nein? Also die Exception alleine macht das noch nicht. Das Verhalten auf die Exception vielleicht.

Kleine Abschweifung:
Es gibt schon Gründe, wieso eine Float-Division durch 0 INF ergibt:
  1. Ein Quotient nähert sich an Unendlich an, wenn der Divisor gegen null geht
  2. jede beliebige reelle als Float/Double/Int/Long darstellbare Zahl wäre kein korrektes Ergebnis auf die Division durch null
  3. null erst recht nicht

Folglich musst du bei der Float-Division nachher prüfen, ob der Prozessor das Ergebnis als "Achtung, das war eine Division durch null" markiert hat. Also einfach ob's = INF ist.

Zurück zu deinem Problem:
Ich hab's eben selber ausprobiert. Bei der Ganzzahldivision wirft BMax tatsächlich keine fangbare Exception Sad . D.h. du kannst auch nicht darauf reagieren. Eine Möglichkeit wäre, eine Funktion dafür zu schreiben:
BlitzMax: [AUSKLAPPEN]
Local a%=0
Print myDivide(15,a)

Function myDivide%(a%, b%)
If b=0 Then Return 0
Return a/b
End Function
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

BladeRunner

Moderator

BeitragDi, Feb 25, 2020 11:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie aber schon an anderer Stelle geschrieben: Es ist ganz miserabler Stil dass so aufzuweichen.
Eine Division durch Null ist eben im Ergebnis nicht definiert und somit keine mathematisch valide Operation.
Das zu umgehen schreit nach Ärger im Verlauf. Lass es bleiben.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
 

sinjin

BeitragMi, März 04, 2020 0:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Das wäre eben kein miserabler Code sondern wäre Teil meines Codes...ob ihr es zulässig findet oder nicht...Meine Frage: Ist es MÖGLICH das 1/0 mein Programm einfach 0 rauskommen lässt in BlitzMAX oder nicht, und einfach weiter macht...Nochmal, in ASM geht es bzw es ging unter DOS. Ob nun ein dickes Fenster kommt oder mein Code einfach weiter macht. Meine Methode wäre schneller, und ich weiß ja worauf ich mich einlasse. Nur die FPU gibt #NAN oder unendlich wieder, die CPU hat dafür halt den Interrupt 0. Kann ich den nicht abfangen? Vielleicht allgemeiner: Wie kann ich Interrupts abfangen?
Ob ich oben in meinem Code sage: Const a%=1 oder halt DIV0=0, wo wäre da der unterschied?
Zu sagen: "Ich weiß es aber warum willst du das haben"....das ist doch keine Antwort....
Es geht mir hauptsächlich ums Modulieren wie: A mod B. Nun ist es aber am Benutzer B einzutragen...klar, ich könnte Fragen ob die Eingabe Null ist....darum geht es mir aber nicht weil das Ergebnis 0 wäre zu geil Very Happy. Und desweiteren ich hasse wenn mein Code nur noch so aussieht: mod(1,2)+div(2,0) Dann will ich ja lieber, wie jeder normale Mensch: 1 mod 2+1/0
  • Zuletzt bearbeitet von sinjin am Mi, März 04, 2020 0:51, insgesamt einmal bearbeitet

BladeRunner

Moderator

BeitragMi, März 04, 2020 0:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Doch, ist es. Es ist der offene Rat mehrerer an Dich: Lass es einfach bleiben.
Ich denke damit haben wir die bestmöglichste Hilfe gegeben, auch wenn dir der Rat vielleicht nicht zusagt.
Du versuchst im gegebenen Beispiel fundamentale Grundlagen der Mathematik für dein Projekt umzubiegen bzw. auszuhebeln. Und auch wenn man es nicht glauben mag, sowas fällt einem *immer* irgendwann auf die Füße.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
 

sinjin

BeitragMi, März 04, 2020 0:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie gesagt, zu sagen: "Klar, es geht..Kein Ding....Aber warum??", gib mir doch bitte mal nen Beispiel Code! Ich bin ja kein Anfänger lol Woher wüsste ich dann das alles? Ausserdem...fundamentale Mathematik...JA! die hebel ich sogar sehr gerne mal aus!!! Nur weil DU sagst, das wäre unzulässig...warum soll mich das aufhalten? Und nochmal, die CPU kann es, ist es in BMAX möglich? Wenn ja wie? Ich weiß in Assembler wird der Code-Pointer vor der Exception plaziert, dh, in ASM muss man halt noch eine Zeile disassemblieren. AAM 0, wäre ja möglich es zu schreiben.
Dazu noch, wenn ich bestimmen kann ob Null rauskommt, damit kann man echt viel machen, z.B. bei 3D einfach weiterrechnen. Am Ende wenn man fragt ob der Pixel denn überhaupt sichtbar ist. Das wäre dann 0 also nein. Auch bei anderen Sachen, wie gesagt, User-Eingaben wäre das kein Problem. Anstatt bei jeder Division zu fragen, ist der Divident 0....OMG
Bei Arrays leuchtet es mir ja noch ein. Obwohl ich bei Slices machmal das Gefühl habe...entweder sind die so tolerant, oder es fehlt was im Debug-Code.
Bei Arrays...hier meckert der Debugger nicht:
Code: [AUSKLAPPEN]
local test$[1]
test[0]="haha"
local t2$[]
Ihr seht, ob zulässig oder nicht...das macht mehr Sinn für mich!
t2=test[..1]+test[6..]
for local a%=0 until t2.length
 print t2[a]
next

Das wäre sowas von unzulässig ! Der meckert auch nicht, wenn ich statt ..1, ..15 eingebe...warum? Im Gegenteil, er "scheint" sogar noch die restlichen undefinierten Strings aufzutreiben Very Happy Da kam halt die Frage...wenn der Compiler jene Abfrage sowieso im Code hat, warum sollte ich es nochmal machen? Naja, da nervt es schon, bzw es kam ja meine Frage auf: Kann ich eine Exception abfangen, ohne es jedes mal hinzuschreiben. Es geht mir ja nicht um die IF und THENs sondern gerade genau um die NICHT hinzuschreiben! Und mein Code macht genau das was er soll! Und nochmal, ob ich oben sage: Const a%=0 oder Div0=0, wo ist das Problem? Es wäre ja cool genug wenn jene Exception meine eigene Funktion dann aufruft, das wäre noch akzeptabel. Jene Funktion würde halt in meinem Code 0 wiedergeben und mein Code macht einfach weiter! EGAL deine Mathematik Very Happy Nichts gegen Leute...Danke für eure Hilfe!
Ich bewege mich halt mal gerne ausserhalb der "Normalen" Mathematik...und wenn das möglich ist, will ich es auch ausnutzen Very Happy
Also in eurer Theorie wäre das nicht möglich:
Code: [AUSKLAPPEN]

b=-1
repeat
  print 15 mod b
  b=b+1
until b=2


In meiner Theorie halt schon:
Code: [AUSKLAPPEN]

function div0%():getexception
  return 0
endfunction
b=-1
repeat
  print 15 mod b '0 if exception
  b=b+1
until b=2

Danach kann ich multiplizieren wie verrückt, das Ergebnis wäre 0 für mich! Und damit nicht darstellbar in 3D-Funktionen..nur ein Beispiel
Wie oft kommt das vor? Etwas öfter als wenn du sagst Const a%=1, sowas braucht man wahrscheinlich nur ein...zweimal im Code.
Es macht mathematisch auch Sinn um die Reihe logisch fortzusetzen:
Code: [AUSKLAPPEN]
local b%=-15
repeat
  if b=0 then print "0:"+0..
  else print (-10 mod b)
  b=b+1
until b=15

x mod b ERGIBT 0!!!!!! Nicht unendlich oder was anderes (auch keine exception anymore)...je nach Programm-Bedürfnis halt.
Wenn du so willst fragt die CPU jedesmal, ob der Wert 0 ist um dann den Interrupt 0 auszuführen, also brauche ich es im Grunde ja nicht jedesmal abzufragen sondern nur ob der Interrupt 0 angesprungen wird...
Und wie ich es sehe wird der Interrupt 0 nicht ohne Hintergrund-Wissen angesprungen...wenn durch 0 teilen nicht möglich wäre, warum dann Interrupt 0? Den will ich einfach nur abfangen!
Nur zur Info, ich habe mein Wissen daher: (früher war ich nie im Internet hab aber die alte Liste..hab auch nen Assembler-Programm unter DOS wo das funktioniert, selbst geschrieben): http://ctyme.com/rbrown.htm
Du kannst es ja löschen, ich weiß externe Links werden nicht gerne gesehen...Auf der anderen Seite höre ich nicht gerne: "Ich weiß wie es geht, aber ich sage es nicht" Wozu dann ein Forum?
Dazu noch, falls es geht unter Windows (hab selber Win 7) warum es nicht sagen? In 5 Jahren ist es eh obslolete, Microsoft eben! Dennoch möchte ich es wissen! Der Interrupt 0 wird auch mit nem neuen Computer nicht so schnell vergessen lol
Und falls ihr Melodyne nicht kennt: Der Erfinder Peter Neubäcker rechnet geardezu mit Nullen Very Happy Der rechnet häufig mit Nullen denke ich. Also kannst das weglassen mit der Mathematik Very Happy

Verflucht...sorry..ist es möglich oder nicht? Klar ASM...aber ist es möglich relativ einfach einzubinden oder nicht? Ich will den Inerrupt 0 abfangen und keine weitere Function die sagt IF 0 THEN!

DAK

BeitragMi, März 04, 2020 10:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Ok, dann mal die lange Antwort Wink

Ob es möglich ist oder nicht hängt nicht am Windows/DOS oder sonstigen Betriebssystemen, sondern rein am Compiler. Wenn du direkt Assembler schreibst (und damit keinen Compiler dazwischen hast), dann ja, ist es absolut möglich irgendsowas zu hacken.

In BlitzMax ist es nicht möglich ohne den Compiler umzuschreiben. Da er Open Source ist, hällt dich keiner davon ab es zu machen. Wie genau das geht weiß hier glaub ich keiner, ohne sich vorher lang einzuarbeiten.

Da ist also deine direkte Antwort: Theoretisch möglich, wenn du den Compiler umschreibst, ziemlich sicher unmöglich, wenn du es nicht tust.

Jetzt dazu warum es eine schlechte Idee ist:

Vergiss mal die Grundlagen der Mathematik und so. Das Problem ist, dass du in einen undefinierten Zustand kommst. Deswegen gibt es die Exception um dir zu sagen "Ich als Compiler/Runtime weiß nicht was du von mir willst und kann deswegen nicht mehr garantieren, dass ich mach was du willst".

Das ist recht ähnlich dazu, was passiert wenn du ungültige Syntax hast. Theoretisch könnte der Compiler versuchen trotz der ungültigen Syntax irgendwie weiter zu machen (wie es z.B. viele HTML-Engines machen). Das führt allerdings dazu, dass Fehler nicht so leicht gefunden werden, weswegen man heutzutage eher dazu übergeht, Fehler hart zu melden.

In Visual Basic z.B. gibt es einen Befehl, der macht genau das. Der Befehl heißt
Code: [AUSKLAPPEN]
On Error Resume Next

Und der sagt, wenn wir eine Exception haben, tu so als gäbe es keine Exception. Ist hald auch eher blöd und deswegen ziemlich verhasst.

Das Problem mit sowas ist nämlich, dass du damit nicht nur beabsichtigte Fehler ignorierst, sondern auch Unbeabsichtigte.

Stell dir z.B. sowas vor:

Code: [AUSKLAPPEN]

Local UNABSICHTLICH_FALSCH_GESETZTE_KONSTANTE:int = 0
Local userInput:Int = Int(Input("Gib eine Zahl ein: ")
print(1/userInput)
print(1/UNABSICHTLICH_FALSCH_GESETZTE_KONSTANTE)


Das ist natürlich ein triviales, winziges Snippet in dem so ein Fehler nie passieren würde. Aber in einem größeren Projekt ist das durchaus möglich, dass man unabsichtlich irgendwo eine Variable falsch setzt oder so.

Wenn der Compiler so arbeitet wie er es aktuell tut, dann würden wir zwar für den userInput eine Exception kriegen, wenn der auf 0 ist, aber auch für die UNABSICHTLICH_FALSCH_GESETZTE_KONSTANTE.

Wenn der Compiler Division durch 0 einfach auf 0 setzt, dann würde der zweite Fehler nicht mehr auffallen.

Deswegen, nach der Devise "Besser Explizit als Implizit" ist die Idee hier so, dass man als Programmierer dem Compiler mitteilt "Ja, ich weiß dass ich hier eventuell durch 0 dividiere, und das ist Absicht.", indem man ein If drum macht, dass diesen Fall abfängt.

In einem üblichen Programm hast du wahrscheinlich ein oder zwei Stellen, wo du absichtlich eine Division durch Null haben könntest, aber hunderte Stellen wo du sowas unabsichtlich haben könntest. Deswegen ist es besser dass du bei den ein oder zwei Stellen dem Compiler explizit sagst, was du willst.

Der andere Vorteil von dem Verhalten ist, dass du bei dem If dem Compiler sagen kannst, was du willst, dass er stattdessen machen soll. Dass er dort dann nämlich einfach 0 ausgibt, ist ja eventuell gar nicht überall im Programm was du willst.

Um das Beispiel also zu verbessern würde man das so machen:

Code: [AUSKLAPPEN]

Local UNABSICHTLICH_FALSCH_GESETZTE_KONSTANTE:int = 0
Local zahl:Int = Int(Input("Gib eine Zahl ein: "))
If zahl<>0 Then
   Print(1/zahl)
Else
   Print("Fehler: du darfst nicht 0 eingeben")
EndIf
print(1/UNABSICHTLICH_FALSCH_GESETZTE_KONSTANTE)


Du hast hier nämlich folgende Vorteile:

    Du fängst den Fehler explizit ab. Damit weiß der Compiler dass es kein Fehler war.
    Du machst das nicht global, das heißt, an der Stelle weiter unten im Code wo es unabsichtlich war, kann dich die Runtime noch immer auf deinen Fehler hinweisen.
    Du kannst ein beliebiges Verhalten definieren, das ausgeführt werden soll, wenn der Fehler auftritt.
    Dieses Verhalten kann im Gegensatz zum Umdefinieren des Interrupt-Handlers nicht nur dafür sorgen dass eine bestimme Zahl drin steht, sondern kann beliebigen Code ausführen um die Situation zu retten.
    Dieses Verhalten kann auch unterschiedlich sein, bei jeder einzelnen Stelle im Code, wo du es einfügst.


Der einzige Nachteil ist:
    Es kostet dich ein paar Zeilen Code (die du aber auch sonst hättest, da du ja den Interrupt-Handler neudefinieren musst).


Dazu kommt, dass deine Idee implizites Verhalten ist. Das ist recht leicht zu vergessen/übersehen, und du wirst ziemlich sicher mal sehr viel Zeit damit verbringen, einen Bug zu suchen, der dadurch versteckt wird, weil du vergessen hast, dass du das so mal reingehackt hast.

Deswegen ist es keine sinnvolle Idee.

Dass es nicht sinnvoll ist, heißt allerdings nicht, dass es dich davon abhalten muss, dass du es trotzdem tust. Es ist nur sehr viel mehr Aufwand als einfach ein If drum rum zu machen und es wird dir später arg in den Hintern beißen.
Gewinner der 6. und der 68. BlitzCodeCompo
 

sinjin

BeitragSa, März 07, 2020 23:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke DAK, bin noch dabei...Klar ist es etwas Aufwand aber dafür muss ich nicht im Kern meines Codes kein IF haben welcher mich wie gesagt iwie stört. Hab die Befehle SIDT und LIDT gefunden, hab allerdings kaum Erfahrung mit Protected-Mode, wie du dir denken kannst wenn ich von DOS bzw von Real-Mode komme. (Bin selber überrascht das ich noch fast alles kann nach so langer Zeit, ist wie Fahrradfahren Very Happy) Ich kann die Interrupt-Liste auslesen...bin dabei Very Happy
Und danke an alle, ich weiß das ist kein Assembler-Forum aber früher habe ich Pascal programmiert und will weiterhin BMAX benutzen. (Hab noch die ältere Version weil bei BMAX-NG, also ich kann meine Programme nicht einfach so kompilieren, weil anscheined kein FASM dabei ist...naja und hab auch kein Bock, wie bei C, mir jede extra Einheit runterzuladen)
Zu diesem Thema noch ein Wort: Es geht nicht um die mathematische Ethik, und es bringt kaum Sinn es mir, oder ich euch, es recht zu machen, ihr baut halt ein IF ein, ich möchte das der Prozessor es macht.
Wenn ich nen Code habe, poste ich es hier. Hab allerdings noch mehr Fragen aber die beziehen sich nicht auf dieses Thema...So schnell werdet ihr mich nicht los Very Happy
Du warst in meinen Augen auch der Einzige der nicht fragt: Was willst du damit...Warum willst du es haben...oder: Das ist mathematisch inkorrekt Very Happy
50 MOD 0 kann ja nicht unendlich sein und 50 wäre auch falsch! Mal ganz doof: ich habe 50 Äpfel und möchte die an 0 Leute verteilen, dann sind die einfach weg!!!!! Bzw die gehören dann niemanden. Ich rede ja von Integern, bei Floats ist es ähnlich, 1/0.5 = 2, aber wenns nahe unendlich geht, dann ist 0 genau gleich wie unendlich, nämlich nicht darstellbar. Das Nichts wie unendlich kann sich niemand vorstellen! Der Computer ist nicht unendlich daher ist Null die logische Möglichkeit, für mich, ihr könnt es ja abfangen, ich will dann einfach weiter machen im Code.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group