Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
code
Anmeldungsdatum: 19.01.2005 Beiträge: 154
|
Verfasst am: 07.04.2005, 18:57 Titel: Überlauf? |
|
|
also ich hab in einem Programm folgenden code verwendet:
allerdings kommt jetzt beim audführen die fehlermeldung <<überlauf>>!
Kann das sein? Kann ich also mit qb nicht mal diese einfache rechnung machen? (ich wollte die sekunden eines tages ausrechnen.) |
|
Nach oben |
|
 |
Paul aka ICC, HV-Freak
Anmeldungsdatum: 11.09.2004 Beiträge: 588 Wohnort: Uelzen
|
Verfasst am: 07.04.2005, 18:59 Titel: |
|
|
Code: |
a&=3600*24
print a&
|
Das sollte gehen  _________________
 |
|
Nach oben |
|
 |
code
Anmeldungsdatum: 19.01.2005 Beiträge: 154
|
Verfasst am: 07.04.2005, 19:16 Titel: |
|
|
geht das bei dir? also bei mir klappts immer noch nicht.  |
|
Nach oben |
|
 |
dreael Administrator

Anmeldungsdatum: 10.09.2004 Beiträge: 2529 Wohnort: Hofen SH (Schweiz)
|
Verfasst am: 07.04.2005, 19:53 Titel: Kleine Abhandlung über Zahlentypen... |
|
|
Die Ursache ist eigentlich klar: Zwei 16-Bit-Integer ergeben multipliziert wiederum einen 16-Bit-Integer (eigentlich vermisse ich die Typenstrenge von ADA und Modula-2 in vielen Programmiersprachen), was in diesem Fall natürlich einen Überlauf ergibt.
Abhilfe: Multiplikation als 32-Bit-Integer:
d.h. jetzt erhält der "*" zwei Parameter als 32-Bit-Integerzahlen.
Oh ja an dieser Stelle eine Antwort auf eine einmal früher eingebrachte Bemerkung, als ich einst einmal so etwas wie
Code: | a% = 5 + CINT(INT(CSNG(h%) * RND)) |
veröffentlicht hatte. Dazu eine genaue Analyse: Das "*" muss hier als einfachgenaue Fliesskommaoperation erfolgen, daher wird hier das h% quasi noch kompatibel vvon % (INTEGER) nach ! (SINGLE) umgewandelt. Nun etwas, woran nur die wenigsten denken, aber man kann es tatsächlich beweisen: INT() liefert entgegen der landläufigen Meinung _kein_ % (INTEGER) oder & (LONGINT) zurück, sondern ! (SINGLE) bzw. sogar # (DOUBLE)! Das "Warum" ist sehr einfach:
Code: | PRINT INT(987654321098.76#) |
In diesem Fall ist das Ergebnis deutlich grösser als der Range einer 32 bit signed integer (&). Ein Vorfahre von QB, nämlich AmigaBASIC auf dem Commodore Amiga (war 1987 herausgekommen), verlangte damals noch exakt übereinstimmende Parameter bei SUB; diese Eigenschaft erlaubte damals den wahren Datentypen ausfindig zu machen, die eine Funktion zurückliefert. Unter QB könnt Ihr eine Schleife der Art
Code: | t1! = TIMER
FOR i&=1& TO 100000&
dummy% = INT(23.7)
NEXT i&
t2! = TIMER
FOR i&=1& TO 100000&
dummy& = INT(23.7)
NEXT i&
t3! = TIMER
FOR i&=1& TO 100000&
dummy! = INT(23.7)
NEXT i&
t4! = TIMER
FOR i&=1& TO 100000&
dummy# = INT(23.7)
NEXT i&
t5! = TIMER
FOR i&=1& TO 100000&
dummy% = INT(23.7)
NEXT i&
t2! = TIMER
PRINT "%:"; t2! - t1!
PRINT "&:"; t3! - t2!
PRINT "!:"; t4! - t3!
PRINT "#:"; t5! - t4! |
d.h. bei der schnellsten Variante findet keine Typenumwandlung statt, womit dies dem zurückgelieferten Datentypen entspricht. Bei Modula-2 und ADA muss man die Typenumwandlung jeweils explizit vornehmen, womit man sich viel bewusster wird, ob man irgendwo eine unnötig teure Fliesskommaoperation einsetzt. Bei QB kann man freiwillig ebenfalls nach der Modula-2/ADA-Philosophie arbeiten; verhilft natürlich zu wesentlich optimaleren Code beim Compiler.
Es ist daher auch überhaupt nicht gleichgültig, ob jemand
Code: | mitte% = 40 - INT(LEN(t$) / 2) |
oder
Code: | mitte% = 40 - LEN(t$) \ 2 |
schreibt. Im ersteren Beispiel werden gleich mehrere unnötige Datentypumwandlungen ausgelöst, d.h. es wird in Wirklichkeit als
Code: | mitte% = CINT(CSNG(40) - INT(CSNG(LEN(t$)) / CSNG(2))) |
ausgeführt, d.h. wir haben gleich 4(!) versteckte und zeitfressende Datentypenumwandlungsoperationen drin + erst noch mit "/" und INT() gleich zwei sehr teure Fliesskommaopeationen.
Dagegen "\" ist eine _echte_ Integeroperation, d.h. wir verlassen den Körper der "%"- und "&"-Zahlen überhaupt nicht und sind daher entsprechend sehr schnell. Daher kann QB den zweiten Ausdruck mit der bestmöglichen Performance durchführen.
Übrigens FIX() verhält sich ganz analog wie INT().
Ich denke, die Assemblerspezialisten hier im Forum sollte all die hier geschilderten Sachverhalte durch Disassemblierung einer compilierten .EXE belegen können. _________________ Teste die PC-Sicherheit mit www.sec-check.net |
|
Nach oben |
|
 |
code
Anmeldungsdatum: 19.01.2005 Beiträge: 154
|
Verfasst am: 07.04.2005, 20:08 Titel: |
|
|
ok danke jetzt hats funktioniert.  |
|
Nach oben |
|
 |
|