abgesehen davon, das mich das Runden bei Pascal gewaltig nervt (ich sehe im Bankers Rounding als einzige Existenzgrundlage, das Bänker sich unrechtmäßig bereichern), ist mir die nächste komische Situation aufgefallen:
Beim Runden von double-Werten rundet das System mit dem Bankers-Rounding, beim Runden von Currency-Werten so, wie ich es mal gelernt habe und damit auch so, wie ich es gerne auf meinen Rechnungen hätte:
17,50€ netto gerundet als Currency ergibt 3,325€ MwSt, also 3,33€. So weit, so schön dachte ich mir...
Um die Werte zu überprüfen, habe mir ein kleines Konsolenprogrämmchen geschrieben:
(meine internen Funktionen myRound, myRoundc spielen hier keine Rolle)
Code: Alles auswählen
program project3;
function myRound(wert: double): double;
begin
myRound := trunc(wert + 0.5);
end;
function myRoundc(wert: currency): currency;
begin
myRoundc := trunc(wert + 0.5);
end;
var x, zins: double;
y: currency;
begin
zins := 0.19;
x := 17.5;
y := 17.5;
writeln;
writeln(x * zins, ' ', Round(x * zins*100)/100, ' ', myRound(x * zins*100)/100, ' ', myRoundc(x * zins*100)/100);
writeln(y * zins, ' ', Round(y * zins*100)/100, ' ', myRound(y * zins*100)/100, ' ', myRoundc(y * zins*100)/100);
readln;
end
Doof nur, das die Werte unter Windows und Linux nicht konsistent sind:
Code: Alles auswählen
Windows, Lazarus 3.6 / fpc 3.2.2 / 64bit und
Windows, Lazarus 2.2.6 / fpc 3.2.2 / 64bit
3.3250000000000002E+000 3.3199999999999998E+000 3.3300000000000001E+000 3.3300000000000001E+000
3.325000000000000000E+00 3.3300000000000001E+000 3.3300000000000001E+000 3.3300000000000001E+000
Windows, fpc 3.2.2 (aus dem Lazarusverzeichnis) /64 bit & 32bit
3.3250000000000002E+000 3.3199999999999998E+000 3.3300000000000001E+000 3.3300000000000001E+000
3.325000000000000000E+00 3.3300000000000001E+000 3.3300000000000001E+000 3.3300000000000001E+000
Linux, Lazarus 3.0 / fpc 3.2.2 / 64bit
3.3250000000000002E+000 3.3199999999999998E+000 3.3300000000000001E+000 3.330000000000000000E+00
3.325000000000000000E+00 3.3199999999999998E+000 3.3300000000000001E+000 3.330000000000000000E+00
Linux, fpc 3.2.2 / 64 bit
3.3250000000000002E+000 3.3199999999999998E+000 3.3300000000000001E+000 3.330000000000000000E+00
3.325000000000000000E+00 3.3199999999999998E+000 3.3300000000000001E+000 3.330000000000000000E+00
die zweite Zeile die mit den Currency-Variablen.
Wichtig sind hier die Werte der 2. Spalte:
3.3199 (Bankers-Rounding, abgerundet; auf dies .9999999x scheiXX ich mal, wird mit double zusammenhängen)
3.3300 (Standard-Rundung; 0.5 wird aufgerundet)
Unter Linux scheint, anders als unter Windows, auch bei Currency-Werten das Bankers-Round genutzt zu werden.
Jetzt stellt sich nur noch die Frage: was ist daran gewollt?
Es hat sich mal jemand dran gemacht, diese Funktion zu definieren:
(Pfade bei mir:)
F:\lazarus\fpc\3.2.2\source\rtl\inc\currh.inc
F:\lazarus\fpc\3.2.2\source\rtl\inc\gencurr.inc
aus gencurr.inc
Code: Alles auswählen
function round(c : currency) : int64;
var
rem, absrem: currency;
begin
{ (int64(tmyrec(c))(+/-)5000) div 10000 can overflow }
result := int64(c);
rem := c - currency(result);
absrem := rem;
if absrem < 0 then
absrem := -absrem;
if (absrem > 0.5) or
((absrem = 0.5) and
(rem > 0)) then
if (rem > 0) then
inc(result)
else
dec(result);
end;
Da steckt viel Überlegung hinter, ob die ganze rumspielerei mit den beiden Variablen sinnführender ist, als die trunc-Variante, mag ich gerade nicht beurteilen.
Aber warum schafft es Code in den fpc, wenn dieser scheinbar nicht unter allen Betriebssystemen ausgeführt wird?
PS: bei der Mehrwertsteuerberechnung tritt dieser Fehler bei allen Werten auf, bei denen der Eurobetrag ungerade ist und der Centbetrag 50.
Also 1,50€, 3,50€, 5,50€, ... 151,50€, ... 7681,50€ ...
PPS: Es muß nur einer der Werte im Round ein Currency-Wert sein, dann wird das Currency-Round durchgeführt; egal an welcher Stelle der Operanden