Hilfe, QBasic rechnet falsch

Hallo,

Statt mit dem Taschenrechner wollte ich lange Zahlenreihen
in QBasic eingeben.
Am Ende wird alles in eine TXT-Datei gespeichert.
Diese TXT-Datei brauche ich zum späteren Ausdruck und zur
Kontrolle.
BETRAG(I) wird am Ende in TXT gespeichert

FOR I …
INPUT A
IF A = 0 THEN… ;(Ausstieg aus Schleife)
BETRAG(I) = BETRAG(I) + A
A = A + A
PRINT A

Es werden eigentlich nur einfache Werte eingetippt, wie
57.00, 12.80, 7.65 etc.

Das funktioniert auch.
Doch plötzlich, an bestimmten Stellen erscheint eine „krumme“
Zahl.
Eigenartigerweise immer an der gleichen Stelle.
Wie z.B. bei 82.30
Da tippe ich dann 13.70 ein.
Angezeigt wird dann 95.99999 statt glatte 96

Rechne ich im Direktmodus beide Zahlen, dann erscheint auch
das richtige Ergebnis (96).

Tippe ich weitere Beträge ein, stimmt irgendwann wieder alles.
Bis irgendwo wieder so krumme Zahlenreihen entstehen.

Das darf und kann doch eigentlich nicht sein.

Was kann das sein?

Klaus

Doch plötzlich, an bestimmten Stellen erscheint eine „krumme“
Zahl.
Eigenartigerweise immer an der gleichen Stelle.
Wie z.B. bei 82.30
Da tippe ich dann 13.70 ein.
Angezeigt wird dann 95.99999 statt glatte 96

Das ist ein typisches Problem bei der Verwendung von Fließkommazahlen. Der Computer rechnet binär, dein Eingaben sind aber dezimal. Vor dem Komma ist das kein Problem, sobald du aber mit Nachkommastellen arbeitest, kann der Computer Dezimalzahlen nicht mehr 1 zu 1 in Binärzahlen abbilden, es kommt zwingend zu Rundungsfehlern (Versuch mal 7/10 als eine Summe von Werten der Folge 1/(2*x); x€N darzustellen).

Für kaufmännisches Rechnen solltest du daher grundsätzlich ausschliesslich mit Ganzzahlen (Integer) arbeiten. Die Aufbereitung der Werte mit zwei Nachkommastellen in der Ein- und Ausgabe musst du dann, wenn die Programmiersprache dies für dich nicht automatisch übernehmen kann, selbst programmieren. QBasic ist für solche Aufgaben nicht unbedingt die geeignetste Sprache.

Gruss
Schorsch

Kleine Korrektur

Vor dem Komma ist das kein Problem

Auch diese Aussage ist nur dann korrekt, wenn du tatsächlich mit ganzzahligen Variablentypen arbeitest. Bei der Darstellung von Ganzzahlen in Variablen vom Typ Gleitkomma werden auch diese intern in Exponentialschreibweise gewandelt und sind entsprechend mit Rundungsfehlern behaftet. Der Rundungsfehler ist dabei um so grösser, je kleiner die Mantisse gewählt wird, bei QBasic dürften das gerade mal 22 bit sein.

Gruss
Schorsch

Äh!

Ich bin ja schon Grufti.
Das bisschen coden habe ich am C64 gelernt.
Dadurch fällt es mir leichter, auch andere Programmiersprachen
zu erlernen.

  1. habe ich keine Progs wie VB oder so,
  2. wollte ich mir die Sache nur erleichtern.

Dafür ein aufwändiges Programm zu coden wäre (für diese Sache)
uneffektiv.
Wenn ich das richtig verstanden habe, dürfte ich nur Ganzzahlen
eingeben.

Vielleicht kapiere ich das nicht richtig.
Die gleiche Programmfolge habe ich mit einem C64 Emulator
getestet (also als C64 Programm).

Einwandfrei. Da ist der Fehler nicht.
Ich bin kein Profi und kein Mathematiker, doch irgendwie ist das
unlogisch.
Ein C64 rechnet ja auch Binär.

QBasic im Vergleich zum C64 Basic ist so, als wenn man
VB mit QBasic vergleicht.

Trotzdem ist das für meine Logik ein Bug.
Ist egal, wie das intern umgerechnet wird.
Wenn da solche Zahlen herauskommen, wird es FALSCH umgerechnet.

Meine Meinung.

Natürlich lässt sich alles Chaotische auch logisch erklären.
Das geht mit Programmiersprachen los.
; als Zeilenende andere unmögliche Zeichen wie gescheifte Klammern.

DOS erkennt Zeilenenden auch ohne ; usw.
Es liegt also an die Entwickler der Prog-Sprachen.

Es mag ja einiges Sinn haben.
Nur ein kleines, unbedeutendes Beispiel:
Statt z.B. A$ wird jetzt geschrieben $A
Warum?
Was bringt das?
NICHTS
Die Funktion, der Sinn ist gleich, nur die Syntax ist anders.
So setzt sich das dann fort.

So hat dann jede Prog.Sprache z.T. eine eigene Syntax.
Total idiotisch.
Oder Javascript.
Ist nicht in der Lage bestimmte, zusammenhängende Befehlszeilen
zu erkennen, es sei, mit dem + Zeichen.

Ich meine:
Es geht auch anders.
Das hat nicht mit „höhere“ Programmierung zu tun, sondern ist einfach
nur chaotisch.
PHP z.B. wird als „einfache“ Programmiersprache angepriesen.
So einfach ist die auch nicht, aber effektiv durchdacht.

Klaus

Hi Klaus,

Trotzdem ist das für meine Logik ein Bug.
Ist egal, wie das intern umgerechnet wird.
Wenn da solche Zahlen herauskommen, wird es FALSCH
umgerechnet.

Im Prinzip hast Du ja auch Recht. Die Programmieren von QBasic hätten eine Stelle weniger anzeigen und dafür runden können. Bei der geringen Kapazität der Rechner damals hat man aber darauf verzichtet.
Wenn Du einen Abakus verwendest, darfst Du halt nicht erwarten, daß er Dir numerische integrale vollautomatisch errechnet. Nimm wenigstens einen Taschenrechner. (VB?) :wink:
VB ist genau so leicht zu bedienen wie das Basic vom C64, sogar die Syntax ist fast identisch. Die Unterschiede sind offensichtlich und VB hilft auch ungefragt. Bei VB mußt Du die Syntax nicht lernen, VB erklärt sie während der Arbeit ständig selbst.

Meine Meinung.

Natürlich lässt sich alles Chaotische auch logisch erklären.
Das geht mit Programmiersprachen los.
; als Zeilenende andere unmögliche Zeichen wie gescheifte
Klammern.

DOS erkennt Zeilenenden auch ohne ; usw.
Es liegt also an die Entwickler der Prog-Sprachen.

Ja, da waren wohl einfach die Entwickler der Editoren und Compiler zu faul, das anders zu machen und haben das dem Anwender aufgebrummt.
Die Vorteile, die es bringt, daß man das Zeilenende selbst markieren muß, sind sehr gering. Auf VB4 bis VB6 trifft das aber nicht zu.

Es mag ja einiges Sinn haben.
Nur ein kleines, unbedeutendes Beispiel:
Statt z.B. A$ wird jetzt geschrieben $A
Warum?
Was bringt das?
NICHTS
Die Funktion, der Sinn ist gleich, nur die Syntax ist anders.
So setzt sich das dann fort.

Beispiel VB? Da reicht A. $ brauchst Du gar nicht mehr schreiben.

So hat dann jede Prog.Sprache z.T. eine eigene Syntax.
Total idiotisch.
Oder Javascript.
Ist nicht in der Lage bestimmte, zusammenhängende
Befehlszeilen
zu erkennen, es sei, mit dem + Zeichen.

Ich meine:
Es geht auch anders.
Das hat nicht mit „höhere“ Programmierung zu tun, sondern ist
einfach
nur chaotisch.
PHP z.B. wird als „einfache“ Programmiersprache angepriesen.
So einfach ist die auch nicht, aber effektiv durchdacht.

Es hilft schon, wenn während dem Tippen die Syntax erklärt wird.
Sieh Dir VB6 mal an.

Gruß, Rainer

Vielleicht kapiere ich das nicht richtig.
Die gleiche Programmfolge habe ich mit einem C64 Emulator
getestet (also als C64 Programm).

Einwandfrei. Da ist der Fehler nicht.
Ich bin kein Profi und kein Mathematiker, doch irgendwie ist
das
unlogisch.
Ein C64 rechnet ja auch Binär.

Das war dann nichts weiter als ein glücklicher Zufall. Der C64 kennt überhaupt noch keine dezidierten Variablentypen für numerische Werte, intern rechnet er, sofern es sich nicht um Schleifeninvarianten handelt, meiner Erinnerung nach grundsätzlich mit Gleitkommawerten. Erst bei der Ausgabe der Werte per print-Befehl rundet er dann wieder.

Ich kann mich aber noch dunkel an Situationen erinnern, in denen Vergleiche (IF A$ = B$ THEN…) an genau diesem Problem fehlschlugen, weil er da eben nicht rundet, und 17,999999998 ist nun mal nicht gleich 18. Und diese Probleme traten schon dann auf, wenn A$ oder B$ als Summe einstelliger ganzer Zahlen gebildet wurden.

Das ist mit modernen Programmiersprachen übrigens nicht anders, das passiert z. B. mit Perl genauso, auch andere Sprachen haben die gleichen Probleme, wenn die Variablen auf den falschen Typ deklariert sind. Daher sollten Variablen mit Festkommawerten grundsätzlich als Integer deklariert werden, auch dann, wenn sie eine feste Zahl von Nachkommastellen haben.

Und, auch in der kaufmännischen Rechnung wichtig, wenn komplexere Rechnungen mit Gleitkommawerten vorgenommen werden müssen, muss der Programmierer immer auf angemessene Rundung achten. Sonst werden aus Rundungsfehlern von millionstel Cent u. U. durch ihre Kumulation am Jahresende leicht mal einige zehntausend Euro Buchungsdifferenz. Gut, vielleicht nicht bei den Grössenordnungen, in denen du rechnest.

Gruss
Schorsch

Schon wieder Korrektur

Das war dann nichts weiter als ein glücklicher Zufall. Der C64
kennt überhaupt noch keine dezidierten Variablentypen für
numerische Werte, intern rechnet er, sofern es sich nicht um
Schleifeninvarianten handelt, meiner Erinnerung nach
grundsätzlich mit Gleitkommawerten. Erst bei der Ausgabe der
Werte per print-Befehl rundet er dann wieder.

Dass ich mich dauernd korrigieren muss… peinlich, peinlich. Natürlich kennt auch das C64-Basic schon Integervariablen, diese werden dann mit % statt $ deklariert. Und sofern auf korrekte Variablendeklaration geachtet wird, rechnet er auch durchaus korrekt. Probleme treten auch hier erst bei falscher Variablendeklaration auf.

Gruss
Schorsch

Hallo Schorsch,

Dass ich mich dauernd korrigieren muss… peinlich, peinlich.
Natürlich kennt auch das C64-Basic schon Integervariablen,
diese werden dann mit % statt $ deklariert. Und sofern auf
korrekte Variablendeklaration geachtet wird, rechnet er auch
durchaus korrekt. Probleme treten auch hier erst bei falscher
Variablendeklaration auf.

Wenn ich das noch recht im Kopf habe war das doch so:
A = Numerisch, Floating Point
A$ = String
A% = Integer

MfG Peter(TOO)