Liebe Leute,
gibt's folgenden Fehler auch noch in der aktuellen Version? (man/frau achte auf den Wechsel von 232,60 nach 23259 (erstes Beispiel))
Grüße Egbert
PROGRAM test; VAR i : integer; Spesen : ARRAY [0..5] OF integer; CONST S : ARRAY [0..5] OF real = (232.60, 232.61, 500.00, 499.00, 499.99, 500.00); BEGIN writeln('----------'); FOR i := 0 TO 5 DO BEGIN writeLn(S[i]); writeLn(S[i]:6:2); Spesen[i] := trunc(S[i] * 100); writeLn(Spesen[i]); writeln('----------'); END; END.
ergibt, übersetzt und ausgeführt mit gpc version 20021128, based on gcc-3.2.1:
---------- 2.326000000000000e+02 232.60 23259 ---------- 2.326100000000000e+02 232.61 23261 ---------- 5.000000000000000e+02 500.00 50000 ---------- 4.990000000000000e+02 499.00 49900 ---------- 4.999900000000000e+02 499.99 49999 ---------- 5.000000000000000e+02 500.00 50000 ----------
Hallo!
On Thu, May 27, 2004 at 08:02:00AM +0200, Dr. Egbert Seibertz wrote:
gibt's folgenden Fehler auch noch in der aktuellen Version? (man/frau achte auf den Wechsel von 232,60 nach 23259 (erstes Beispiel))
(Ich habe das Programm etwas umgeschrieben und jetzt läuft es:)
program test; var i : Integer; Spesen: array [0..5] of Integer; q : Real; const S: array [0..5] of Real = (232.60, 232.61, 500.00, 499.00, 499.99, 500.00); begin WriteLn('----------'); for i := 0 to 5 do begin WriteLn(S[i]); WriteLn(S[i] : 6 : 2); q := S[i] * 100.0; Spesen[i] := Trunc(q); WriteLn(Spesen[i]); WriteLn('----------') end end.
Mit der Ausgabe: ---------- 2.326000000000000e+02 232.60 23260 ---------- 2.326100000000000e+02 232.61 23261 ----------
und so weiter.
Eike
Eike Lange schrieb:
Hallo!
On Thu, May 27, 2004 at 08:02:00AM +0200, Dr. Egbert Seibertz wrote:
gibt's folgenden Fehler auch noch in der aktuellen Version? (man/frau achte auf den Wechsel von 232,60 nach 23259 (erstes Beispiel))
(Ich habe das Programm etwas umgeschrieben und jetzt läuft es:)
Das ursprüngliche Programm sagt auch mit der aktuellen GPC-Version 23259.
Dies ist aber nicht zwangsläufig ein Fehler. Schließlich rechnest du hier mit Fließkomma-Zahlen, die von Natur aus ungenau sind (sofern sie nicht eine endliche *Binär*-Bruch-Darstellung haben, was bei Hundersteln nicht der Fall ist).
Der tatsächlich verwendete Wert *muss* also ein bisschen zu groß oder zu klein sein. (Je nachdem, was näher ist. "Zufälligerweise" ist bei 232.60 bei `Real' offenbar der etwas kleinere Wert näher. Bei `ShortReal' und `LongReal' wäre es der größere. Dort geht es dann bei anderen Zahlen schief.) Nach der Multiplikation bleibt der Wert dann natürlich zu groß/klein, es sei denn, er wird (wiederum "zufällig") durch einen Rundungsfehler ausgeglichen.
Und da `Trunc' knallhart abschneidet (wie es ja sein soll), wird aus 23259.999999999999999 eben 23259. Mit `Round' fällt so ein Fehler weniger auf, ist aber prinzipiell auch möglich.
Daher die Moral von der Geschichte: Für Geldbeträge immer Integer-Typen (in der kleinsten Einheit, hier also Cent) verwenden. Unter http://gnu-pascal.de/contrib/frank/misc/moneyutils.pas habe ich übrigens eine kleine Unit zur komfortableren Ein-/Ausgabe solcher Typen.
Frank