Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi ungültiger Extended-Value (https://www.delphipraxis.net/63333-ungueltiger-extended-value.html)

matthiasl 17. Feb 2006 02:06


ungültiger Extended-Value
 
Schönen guten Tag erstmal,

ich habe gerade beim Übertragen von Access(DAO)-Daten in MySql einen Extended-Wert gefunden, der sich beim Kopieren nicht in Zeichen umwandeln ließ. Mit einem Hex-Editor hab ich den seltsamen Wert gesucht und gefunden.

Delphi-Quellcode:
var
  e:Extended;
  p:^Byte;
begin
  p:=@e;
  p^:=$00; inc(p);
  p^:=$00; inc(p);
  p^:=$00; inc(p);
  p^:=$00; inc(p);
  p^:=$00; inc(p);
  p^:=$00; inc(p);
  p^:=$00; inc(p);
  p^:=$C0; inc(p);
  p^:=$FF; inc(p);
  p^:=$FF; inc(p);

  ShowMessage(FloatToStr(e)+'   und   '+VarToStr(e));
end;
Frage 1: Kann mir jemand erklären, wie es eine Extended-Variable geben kann, die keinen gültigen Wert enthält?

Frage 2: Kann mir jemand erklären, woran man solche Werte identifizieren kann? Eine Funktion wie "isValidFloat(e:Extended):Boolean" wäre das Ziel.

Frage 3: Wie kann es zu solchen Werten kommen? Gibt es andere Leute, die aus einer ansonsten intakten Access-Datenbank soetwas rausgelesen haben?

Jeder auch noch so kleine Ansatz/Idee wird hilfreich sein.

jfheins 17. Feb 2006 11:36

Re: ungültiger Extended-Value
 
Zitat:

Frage 1: Kann mir jemand erklären, wie es eine Extended-Variable geben kann, die keinen gültigen Wert enthält?
Ja, durch eine nicht definierte Rechnung. sqrt(-3) wäre zum Beispiel keine (relle) Zahl, oder ?
http://de.wikipedia.org/wiki/NaN

Zitat:

Frage 3: Wie kann es zu solchen Werten kommen? Gibt es andere Leute, die aus einer ansonsten intakten Access-Datenbank soetwas rausgelesen haben?
NaN wird auch gerne für "undefiniert" oder "nicht angegeben" verwendet ...

Zitat:

Frage 2: Kann mir jemand erklären, woran man solche Werte identifizieren kann? Eine Funktion wie "isValidFloat(e:Extended):Boolean" wäre das Ziel.
Ja, das sind spezielle Konstanten, um spezielle Zahlen auszudrücken ...
http://de.wikipedia.org/wiki/IEEE_75...tellbare_Werte

Folgendes Beispiel sollte dir z.B. minus unendlich geben ;)
Delphi-Quellcode:
 p:=@e;
  p^:=$00; inc(p);
  p^:=$00; inc(p);
  p^:=$00; inc(p);
  p^:=$00; inc(p);
  p^:=$00; inc(p);
  p^:=$00; inc(p);
  p^:=$00; inc(p);
  p^:=$80; inc(p);
  p^:=$FF; inc(p);
  p^:=$FF; inc(p);

  ShowMessage(VarToStr(e));
Daraus können wir sagen, dass momentan das höchste Bit das Vorzeichen ist, dann 2 Bytes Exponent folgen und der Rest ist Mantisse ;)

Khabarakh 17. Feb 2006 12:03

Re: ungültiger Extended-Value
 
NaN entsteht außerdem, wenn sich ein Wert nicht ohne Widersprüchen berechnen lässt.
Beispiel +Inf * 0
1. Regel: 0 multipliziert mit x ergibt immer 0.
2. Regel: +Inf multipliziert mit x (positiv) ergibt immer +Inf.
=> Widerspruch

matthiasl 17. Feb 2006 12:13

Re: ungültiger Extended-Value
 
Danke, Julius.

Das trifft den Punkt genau. Ich hoffe, das anderen damit diese Fehlersuche erspart bleibt. Ich werde eine IsValid-Routine schreiben und sie hier posten.

Khabarakh 17. Feb 2006 12:30

Re: ungültiger Extended-Value
 
Delphi-Referenz durchsuchenIsInfinite
Delphi-Referenz durchsuchenIsNan
;)

jfheins 17. Feb 2006 12:37

Re: ungültiger Extended-Value
 
Genau ... folgender Code:
Delphi-Quellcode:
uses Math;

function IsValid (e: Extended): Boolean;
begin
  Result := (not IsNan (e)) and (not IsInfinite(e));
end;
:mrgreen:

matthiasl 18. Feb 2006 06:19

Re: ungültiger Extended-Value
 
Danke, Leute.

Leider muß ich sagen, daß ich Delphi 5.0 benutze und die Funktionen "IsNan" und "IsInfinite" anscheinend erst später dazugekommen sind.

Ich habe mich zu folgenden Routinen durchgerungen, um das Transportproblem DAO->MySql zu beseitigen. Dabei war eine Überlegung: Ein Fehler ist schlecht, ein unsichtbarer Fehler eine Katastrophe. Ich wollte also das Problem nicht einfach verstecken, sondern mir die Möglichkeit offen halten, einen eventuell ursächlichen Fehler irgendwann auch mal zu finden.

Delphi-Quellcode:
  procedure ValidateSingle(var Value:Single);
    // 4 Byte Float-Value
    // SEEEEEEE MMMMMMMM MMMMMMM MMMMMMM
    var
      c:Cardinal;
    begin
      c:=Cardinal(Pointer(Integer(@Value)+0)^);
      if ((c shr 24) and $7f)=$7f then begin
        case ((c shr 22) and 3) of
          2 : begin // INF
                if ((c shr 31) and 1)=0 then begin // Positiv
                  if MessageDlg('Es ist ein Wert von "positiv Unendlich" aufgetreten. Wollen Sie den Wert auf Null setzen?',mtConfirmation,[mbYes,mbNo],0)=idYes then
                    Value:=0;
                end else begin // Negativ
                  if MessageDlg('Es ist ein Wert von "negativ Unendlich" aufgetreten. Wollen Sie den Wert auf Null setzen?',mtConfirmation,[mbYes,mbNo],0)=idYes then
                    Value:=0;
                end;
              end;
          3 : begin // NAN
                if MessageDlg('Es ist ein ungültiger Fließkomma-Wert aufgetreten. Wollen Sie den Wert auf Null setzen?',mtConfirmation,[mbYes,mbNo],0)=idYes then
                  Value:=0;
              end;
        end;
      end;
    end;

  procedure ValidateDouble(var Value:Double);
    // 8 Byte Float-Value
    // SEEEEEEE EEEMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM
    var
      c:Cardinal;
    begin
      c:=Cardinal(Pointer(Integer(@Value)+4)^);
      if ((c shr 21) and $3ff)=$3ff then begin
        case ((c shr 19) and 3) of
          2 : begin // INF
                if ((c shr 31) and 1)=0 then begin // Positiv
                  if MessageDlg('Es ist ein Wert von "positiv Unendlich" aufgetreten. Wollen Sie den Wert auf Null setzen?',mtConfirmation,[mbYes,mbNo],0)=idYes then
                    Value:=0;
                end else begin // Negativ
                  if MessageDlg('Es ist ein Wert von "negativ Unendlich" aufgetreten. Wollen Sie den Wert auf Null setzen?',mtConfirmation,[mbYes,mbNo],0)=idYes then
                    Value:=0;
                end;
              end;
          3 : begin // NAN
                if MessageDlg('Es ist ein ungültiger Fließkomma-Wert aufgetreten. Wollen Sie den Wert auf Null setzen?',mtConfirmation,[mbYes,mbNo],0)=idYes then
                  Value:=0;
              end;
        end;
      end;
    end;

  procedure ValidateExtended(var Value:Extended);
    // 10 Byte Float-Value
    // SEEEEEEE EEEEEEEE MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM
    var
      c:Cardinal;
    begin
      c:=Cardinal(Pointer(Integer(@Value)+6)^);
      if ((c shr 16) and $7fff)=$7fff then begin
        case ((c shr 14) and 3) of
          2 : begin // INF
                if ((c shr 31) and 1)=0 then begin // Positiv
                  if MessageDlg('Es ist ein Wert von "positiv Unendlich" aufgetreten. Wollen Sie den Wert auf Null setzen?',mtConfirmation,[mbYes,mbNo],0)=idYes then
                    Value:=0;
                end else begin // Negativ
                  if MessageDlg('Es ist ein Wert von "negativ Unendlich" aufgetreten. Wollen Sie den Wert auf Null setzen?',mtConfirmation,[mbYes,mbNo],0)=idYes then
                    Value:=0;
                end;
              end;
          3 : begin // NAN
                if MessageDlg('Es ist ein ungültiger Fließkomma-Wert aufgetreten. Wollen Sie den Wert auf Null setzen?',mtConfirmation,[mbYes,mbNo],0)=idYes then
                  Value:=0;
              end;
        end;
      end;
    end;

  procedure ValidateVariant(var Value:Variant);
    begin
      case tVarData(Pointer(@Value)^).VType of
        varSingle:ValidateSingle(tVarData(Pointer(@Value)^).VSingle);
        varDouble:ValidateDouble(tVarData(Pointer(@Value)^).VDouble);
      end;
    end;
Herzlichen Dank nochmal. :-)

jfheins 18. Feb 2006 19:59

Re: ungültiger Extended-Value
 
Hast du auch uses Math; beachtet ?

Weil das müsste auch dei Delphi 5 schon dabei sein ... :gruebel:

matthiasl 19. Feb 2006 03:46

Re: ungültiger Extended-Value
 
Hallo Julius,

die Unit Math enthält bei Delphi 5 wirklich noch nicht diese Funktionen.

Wie ist das bei Delphi 6 denn realisiert? (Wenn es ungesetzlich ist, hier Borland-Code zu posten, muß ich mir mein Delphi 6 eben mal wieder installieren.)

Matthias


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:18 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz