Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Zahlenverwirrung?


cyberhawk - So 04.06.06 12:40
Titel: Zahlenverwirrung?
Hallo, ich muss für die Schule ein Programm schreiben, das die Stromstärke einer Spule beim Einschalten und Ausschalten ausrechnet... Hab schon für den Einschaltmoment (glaube ich) eine alpha-Version fertig^^. Eine Frage habe ich noch. Das e ist bei mir als eine real Variable mit dem Wert 2,178 initialisiert. Wie kriege ich Delphi dazu, 1 - e zu rechnen? Es spuckt die Fehlermeldung aus, es könne keine reals von Integers abziehen.


Gausi - So 04.06.06 12:43

Hallo und :welcome: in der Entwickler-Ecke!

Ich glaube eher, dass das Problem ist, dass du das Ergebnis als Integer deklariert hast. Das Ergebnis einer Rechenoperation mit Real-Werten muss aber auch Real sein, kein Integer.

Zeig mal etwas Code, dann kann man das besser sagen ;-)


Fighter#1 - So 04.06.06 12:49

also, mein delphi kann das.
Zeig doch mal ein bisschen code :-)
[Edit] Och nee schon wieder zu spät :crying: :motz: [/Edit]


cyberhawk - So 04.06.06 12:55

hmm... ich dachte es würde nicht gehen... naja :) hier ist jedenfalls der code:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
var dummy : integer;
begin
e:=2.718;
dummy:= -t div tau;

repeat
e:=e*e;
dummy:=dummy-1;
until dummy = 0;

dummy:= 1.00 - e;  hier taucht die Fehlermeldung auf.
Ie:=I0 * dummy;


Listbox1.Items.Add(inttostr(Ie) + '(' + inttostr(t) + ')');


Moderiert von user profile iconGausi: Delphi-Tags hinzugefügt


Gausi - So 04.06.06 13:08

Wie ich sagte: Deklariere dummy als Real, und es sollte gehen ;-)

Evtl. musst du dann noch das DIV durch ein / ersetzen, da bin ich jetzt nicht sicher, was der Compiler da erlaubt.


cyberhawk - So 04.06.06 13:11

Jo, du hattest recht ;).

Aber wie gebe ich das Ergebnis jetzt aus? Inttostr funzt da nicht mehr, weil ich Ie und I0 jetzt auch als real deklariert habe (sonst gibts wieder Fehlermeldungen).


Gausi - So 04.06.06 13:14

Dann nimm FloatToStr, oder ggf. FloatToStrF. Zu den Parametern bitte in die Hilfe gucken, damit komme ich auch immer durcheinander ;-)


cyberhawk - So 04.06.06 13:24

Ok, jetzt kann ich alles starten, aber das wenn ich die Prozedur ausführe, stürzt alles ab (Exception class EOverflow "Floating point overflow") und zwar bei dieser Zeile:

e:=e*e;


JayEff - So 04.06.06 13:30

Nun (neue-frage-neue-topic-sag), bei jeder Schleifenwiederholung kommt bei e eine ziemliche menge an Dezimalziffern dazu, und irgentwann gibt jedes Dezimalformat den Geist auf. Du solltest da immer auf sagen wir 10 ziffern Runden (Suche in: Delphi-Forum, Delphi-Library RUNDE AUF STELLE sollte weiterhelfen), dann passiert sowas nicht.


Allesquarks - So 04.06.06 16:34

Nep!

Also ich würde zunächst nicht beschränkend von Dezimalziffern sprechen, sondern davon dass die Zahl wächst. Da e sowieso unendlich viele Nachkommastellen hat kommen bei einer Multiplikation mit sich selbst auch keine hinzu, sondern sie bleiben einfach abzählbar.
Im computer stellt man eine Zahl anders dar, da man keinen unendlich großen Speicher hat, und zwar häufig in sogenannten Fließkommazahlen (floats (spezialfall: real) siehe IEEE 754), die automatisch den Teil den sie aufgrund ihrer beschränkten Größe nicht darstellen können, abschneiden. Das Problem lässt sich also (siehe IEEE 754) durch runden nicht umgehen, sondern durch kleinere Schleife, größeres Zahlenformat unter Umständen auch nur andere Ausführungsreihenfolge, das kommt immer auf die individuelle Fragestellung an.


JayEff - Mo 05.06.06 16:36

Wie auch immer.
Die Zahl ist 2.718, reden wir von 2. vieliel passt in Extended? Richtig: 1.1 x 10^4932 (puh) Nun rechne um, wieviel das in etwa mit 2.718^X ist und dann weist du, wieviele Schleifendurchgänge dein Programm aushält (das ist natürlich ne vereinfachung und kann evtl für deine Zwecke nicht ausreichend sein. In dem Fall kann dir sicher Allesquarks weiterhelfen.


alzaimar - Mo 05.06.06 17:55

Stimmt alles nicht :mrgreen:
Das Problem ist der berühmte Vergleich einer Real-Zahl mit 0. Das kann nicht gut gehen.
Besser so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
var 
  Zaehler : integer;
  e,x : Extended;
begin
  e:=2.718;
  Zaehler := -t div tau;

  repeat
    e := e*e;
    Zaehler := Zaehler - 1;
  Until Zaehler = 0;
  
  x := 1.00 - e;  hier taucht die Fehlermeldung auf.
  Ie:=I0 * x;
  Listbox1.Items.Add(inttostr(Ie) + '(' + inttostr(t) + ')');
...

Wobei man die repeat-Schleife durch eine einfache Formel ersetzen könnte, denn e wird schließlich 2^(-t div tau) mal mit sich selbst multipliziert, ergo sollte sich die Schleife auf e := Power (e, Power (2, -t div tau)) reduzieren lassen, aber da bin ich mir jetzt nicht so sicher ...


JayEff - Di 06.06.06 02:23

Puh stimmt wenn dummy jetzt plötzlich mit nem real deklariert ist ... hehe .. aber hätte man da nicht auch ne For schleife machen können? For i:=0 to Zähler in unserem Fall ... naja, wie auch immer, ich vermute, deine Lösung funktioniert ^^


alzaimar - Di 06.06.06 08:03

user profile iconJayEff hat folgendes geschrieben:
... aber hätte man da nicht auch ne For schleife machen können? For i:=0 to Zähler in unserem Fall ...

Logisch, aber ich wollte den Originalcode nicht verändern. Es geht ja auch ganz ohne Schleife.
user profile iconJayEff hat folgendes geschrieben:
naja, wie auch immer, ich vermute, deine Lösung funktioniert ^^

Vorsicht ist die Mutter der Porzellankiste. :wink: