Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Prism Migration nach .NET: Bit-Operatoren und Double (https://www.delphipraxis.net/102700-migration-nach-net-bit-operatoren-und-double.html)

dkoehler 2. Nov 2007 17:44


Migration nach .NET: Bit-Operatoren und Double
 
Ich möchte folgenden Code von Delphi für Win32 nach Delphi für .NET portiern:
Delphi-Quellcode:
function IsNegZero(const AValue: Double): Boolean;    
begin
  Result := PInt64(@AValue)^ = $8000000000000000;
end;

function IsPosZero(const AValue: Double): Boolean;
begin
  Result := PInt64(@AValue)^ = $0000000000000000;
end;
Der Code muß geändert werden, weil ja die Pointer-Zauberei nun in Delphi für .NET nicht mehr funktioniert. Was das ganze außerdem noch schwer macht ist die Tatsache, daß Double in der Delphi-Hilfe nicht extra dokumentiert ist.

a) Weiß jemand, ob Double unter .NET sich genauso verhält wie unter Win32 in bezug auf das Vorzeichen, d.h. daß zumindest intern zwischen positiver und negativer Null unterschieden wird?

b) Weiß jemand, wie man das abfragen kann? Ich habe es mit Bit-Operatoren versucht, aber erhalte z.B. in der Zeile:
Delphi-Quellcode:
Result := (AValue and $8000000000000000) = $8000000000000000;
die Fehlermeldung: "Operator not applicable to this operand type" bezüglich AND.

Bernhard Geyer 2. Nov 2007 17:53

Re: Migration nach .NET: Bit-Operatoren und Double
 
Unter .NET würde ich kein solches Bit-Gefummele mehr machen und einfach per

Delphi-Quellcode:
function IsNegZero(const AValue: Double): Boolean;    
begin
  result := (AValue <= 0);
end;

function IsPosZero(const AValue: Double): Boolean;
begin
  Result := (AValue >= 0);
end;
Dann noch noch nach jeder Funktion ein inline ergänzt und der Code dürfte schneller sein als dein alter Code da er einen Funktionscall einspart.

Hawkeye219 2. Nov 2007 18:08

Re: Migration nach .NET: Bit-Operatoren und Double
 
Hallo Bernhard,

ich glaube, hier soll auf die positive und negative Null getestet werden.

Gruß Hawkeye

dkoehler 2. Nov 2007 18:16

Re: Migration nach .NET: Bit-Operatoren und Double
 
Zitat:

Zitat von Bernhard Geyer
Unter .NET würde ich kein solches Bit-Gefummele mehr machen und einfach per

Delphi-Quellcode:
function IsNegZero(const AValue: Double): Boolean;    
begin
  result := (AValue <= 0);
end;

function IsPosZero(const AValue: Double): Boolean;
begin
  Result := (AValue >= 0);
end;

Dieser Code funktioniert nicht, weil die Vergleichsoperatoren eben nicht zwischen positiver und negativer Null unterscheiden (siehe IEEE 754).

Christian S. 2. Nov 2007 18:22

Re: Migration nach .NET: Bit-Operatoren und Double
 
Die BitConverter.DoubleToInt64Bits-Methode könnte Dir helfen, die Bits zu verlgeichen.

Dax 2. Nov 2007 18:27

Re: Migration nach .NET: Bit-Operatoren und Double
 
Falls du nicht den unsafe-Code-Umweg, den Christian vorschlägt, gehen willst, könnte folgendes funktionieren. Ich hoffe, Delphi untersützt sowas, ansonsten nutze direkt den C#-Code (falls er denn funktioniert)
Code:
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Explicit)]
struct DoubleInt64Union
{
  [FieldOffset(0)]
  public readonly double Double;
  [FieldOffset(0)]
  public readonly long Int64;

  public DoubleInt64Union(double d)
  {
    this.Double = d;
  }

  // Zum Vergleich, das BitConverter-Teil
  public static unsafe long DoubleToInt64Bits(double value)
  {
    return *((long*)&value); // <- das hast du in Delphi auch getan
  }
}
Das ist im Prinzip das selbe wie variante Records in Delphi, und du kannst wie gehabt das Int64-Feld mit deinem $(0|8)0* vergleichen.

dkoehler 2. Nov 2007 19:12

Re: Migration nach .NET: Bit-Operatoren und Double
 
Danke für die Hilfe! Ich habe gemäß Christians Vorschlags, BitConverter.DoubleToInt64Bits benutzt. Offenbar ist der entgegen Dax' Bedenken doch "safe". Jedenfalls beschwert sich der Compiler nicht. Hier mein Code (noch ungetestet):

Delphi-Quellcode:
function IsNegZero(const AValue: Double): Boolean;
var
  D: Int64;
begin
  D := BitConverter.DoubleToInt64Bits(AValue);
  Result := D = $8000000000000000;
end;

function IsPosZero(const AValue: Double): Boolean;
var
  D: Int64;
begin
  D := BitConverter.DoubleToInt64Bits(AValue);
  Result := D = $0000000000000000;
end;

Dax 2. Nov 2007 19:19

Re: Migration nach .NET: Bit-Operatoren und Double
 
"Unsafe Code" bedeutet auch nur, dass die Runtime in der Methode an manchem Stellen mit nicht verwaltetem Speicher arbeitet - sprich: Zeigern - also Speicher, von dem sie nie weiß, wann er gültig ist und wann er ungültig wird. Daraus folgt, dass die Zeiger nicht durch den GC gejagt werden und bei falschem rumgezeigere tatsächlich Speicherlecks entstehen. In den BitConverter-Methoden ist das natürlich nicht der Fall, da kein Speicher alloziert wird, daher sind diese wirklich gewissermaßen "safe".

Bernhard Geyer 2. Nov 2007 21:51

Re: Migration nach .NET: Bit-Operatoren und Double
 
Zitat:

Zitat von dkoehler
Dieser Code funktioniert nicht, weil die Vergleichsoperatoren eben nicht zwischen positiver und negativer Null unterscheiden (siehe IEEE 754).

Also manchmal sollte man doch genauer lesen was der Fragesteller wollte :wall:


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:55 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