Wenn Float-Zahlen nicht wie erwartet sondern nur mit vielen Nachkommastellen angezeigt werden, so ist das
im Prinzip unvermeidbar. In der Mathematik liegen reelle Zahlen unendlich dicht, das heißt, man findet bei zwei Zahlen immer eine die dazwischen liegt, egal wie stark man "hineinzoomt". Im Computer geht das nicht, weil für eine Floatzahl nur eine endliche Zahl von Bits zur Verfügung stehen, das heißt man kann nur bis zu einer gewissen Grenze "hineinzoomen", und dann sieht man, dass die Zahlen auf einem Gitter verteilt angeordnet sind. Wenn du also die Zahl 2.7 erwartest, dann ist in diesem Fall eben 2.7000000000002 die Zahl auf demjenigen Gitterpunkt, der der "Wunsch-Zahl" 2.7 am nächsten liegt.
Da kannst du runden wie du willst, denn das Ergebnis der mathematischen Rundung (2.7) wird ja wieder nicht auf einem Gitterpunkt liegen.
Man kann dem Problem oft ausweichen, wenn man zu einem anderen Datentyp geht (double statt single oder extended, oder auch umkehrt), oder eine andere Funktion zur Stringumwandlung wählt.
Bei deinem konkreten Beispiel wundert mich allerdings, dass das Problem überhaupt auftritt. Denn wenn du einen Feldwert als "AsCurrency" abfragst, ist das Ergebnis vom Typ Currency, das ist eigentlich ein mit 10000 multiplizierter Integer. Die Frage wäre in diesem Zusammenhang: Welchen Typ hat rBetrag? Ist das ein Double/Single/Extended? Dann kann das Problem wie beschrieben auftreten. Oder ist es ein Currency? Dann sollte es nicht auftreten.
Mit dem folgenden Code kann ich das nachstellen (Formular mit einem Button und einem TMemDataset):
Code: Alles auswählen
procedure TForm1.Button1Click(Sender: TObject);
var
v: Currency; // ---> korrekt 2.7
// v: Double; // ---> "falsch" 2.7000000000000002
// v: extended; // ---> korrekt 2.7
begin
MemDataset1.First;
v := MemDataset1.Fields[0].AsCurrency;
ShowMessage(Format('%g', [v]));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
with MemDataset1 do
begin
FieldDefs.Add('Betrag', ftCurrency);
CreateTable;
Open;
AppendRecord([2.7]);
end;
end;
Um zwei Float-Zahlen auf Gleichheit zu prüfen, solltest du nie den '=' Operator verwenden, sondern die Funktion SameValue aus der Unit Math, die einen Toleranz-Bereich um jede der beiden Zahlen zulässt. Je nachdem wieviel gerechnet wurde, um zu den zu vergleichenden Zahlen zu gelanden, musst du sogar einen eigenen Toleranz-Bereich angeben, den die Ungenauigkeit können sich während der Rechnung aufgeschaukelt haben:
Code: Alles auswählen
// nicht so: if rBetrag = 2.7 then
// sondern so:
if SameValue(rBetrag, 2.7) then
// oder
if SameValue(rBetrag, 2.7, 1E-12) then // 1E-12 ist der zulässige Abstand zwischen den beiden Zahlen, bei dem trotzdem noch Gleichheit herrschen soll.