Einzelnen Beitrag anzeigen

Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.611 Beiträge
 
#1

Int und Frac schlecht bei Nachkommavergleichen

  Alt 3. Jul 2002, 10:05
Hi,

mal keine Frage, sondern ein Hinweis für die Knowledge-Base hier

Problem:
Es kann unter Umständen wichtig sein, die Nachkommastelle einer Zahl auf einen Bestimmten Wert abzuprüfen.

Meine Erste Idee war folgendes:

Code:
function CheckFracValue(x, y : Real) : Boolean;
begin
   result := false;
   if ( frac(x) = y ) then
      result := true;
end;
Normalerweise müsste der Aufruf CheckFracValue(200204.02, 0.02) eigentlich true zurückliefern. Tut er aber nicht, da frac(200204.02) nicht 0.02 sondern 0.1999999999... zurückliefert.

Debugging im Assemblercode der native - Funktion von Delphi hat ergeben, das es durch die Gleitkommadarstellung bestimmte Nachkommawerte gibt, die nicht eineindeutig sind. So wird ,02 eben immer als ,0199... dargestellt. Das führt bei einem Vergleich, der auf Bitebene durchgeführt wird eben zu Unterschieden und damit zum falschen Ergebnis.

Die Funktion Frac(x: real) : real liefert deshalb zum Teil nicht unbedingt korrekte oder zumindest nicht unbedingt brauchbare Ergebnisse zurück. Gleiches tritt beim Int(x: real) : real - Aufruf auf, der nur den Vorkommaanteil einer Zahl zurückliefert:

Code:
   assert( Int(200204.02) + 0.02 <> 200204.02 );
liefert beispielsweise vollkommen falsch ein True zurück.

Lösung:
Der Vergleich darf nicht auf der Nachkommaebene, sondern vor dem Komma durchgeführt werden, und zwar nicht mit Gleitkommazahlen sondern anhand von Integerwerten.

Code:
function CheckFracValue(x, y:real; decimals : integer) : boolean;
begin
   result := false;
   if ( round( (Int(x) + y) * decimals) = round( x * decimals)) ) then
      result := true;
end;
Wobei Decimals bei 2 Nachkommastellen 100 ist, bei 3 eben 1000 bzw. bei einer eben 10.

Andere Vorschläge dieses Problem zu lösen sind immer willkommen

Bis denne,

Sebastian
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat