Delphi-PRAXiS
Seite 4 von 4   « Erste     234   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Bit-Schiebereien (https://www.delphipraxis.net/180297-bit-schiebereien.html)

Mavarik 10. Mai 2014 12:48

AW: Bit-Schiebereien
 
Zitat:

Zitat von Sir Rufo (Beitrag 1258460)
Zitat:

Zitat von p80286 (Beitrag 1258457)
!Danke!:-D

K-H

Bitte :)

Ein kleines Performance-Update habe ich auch noch eingebaut :)

Sehr nett... Coole Idee, sehr Variable, aber auf keinen Fall so schnell wie ein Varianten Record...

Aber da wir immer noch nicht die Struktur kennen...

Mavarik

himitsu 10. Mai 2014 14:17

AW: Bit-Schiebereien
 
Zitat:

Zitat von Sir Rufo (Beitrag 1258450)
Delphi-Quellcode:
  LClass := _Types[LType]; // Bei einem unbekannten Typen wird hier eine Exception geworfen
  Result := LClass.Create(LData);

Nur, wenn es den Speicherbereich zufällig nicht gibt, oder wenn die Index-Prüfung im Compiler aktiviert wurde.

Aber die Chance ist recht groß, daß es beim Create knallt.

Sir Rufo 10. Mai 2014 22:02

AW: Bit-Schiebereien
 
Zitat:

Zitat von himitsu (Beitrag 1258501)
Zitat:

Zitat von Sir Rufo (Beitrag 1258450)
Delphi-Quellcode:
  LClass := _Types[LType]; // Bei einem unbekannten Typen wird hier eine Exception geworfen
  Result := LClass.Create(LData);

Nur, wenn es den Speicherbereich zufällig nicht gibt, oder wenn die Index-Prüfung im Compiler aktiviert wurde.

Aber die Chance ist recht groß, daß es beim Create knallt.

Öhm, das ist mir bei einem
Delphi-Quellcode:
TDictionary
noch nicht aufgefallen.
Kannst du das mal erläutern?

Sir Rufo 12. Mai 2014 08:59

AW: Bit-Schiebereien
 
Sodele, ich habe die Methode nochmals überarbeitet und jetzt kann man auch die vollen 32bit für einen Integer auslesen, ohne dass es einem um die Ohren fliegt ;)

Im Debug-Mode bleibt es bei ca. 16ms und im Release-Mode sind es ca. 7ms (jeweils für 1.000.000 Abfragen). Ich denke mal, das müsste von der Geschwindigkeit ausreichen :stupid:

Delphi-Quellcode:
unit BaseData;

interface

uses
  System.SysUtils;

type
  TBaseData = class
  private
    FData : TBytes;
  protected
    function GetData( const Index : integer ) : integer;
  public
    constructor Create( AData : TBytes );
  end;

implementation

{ TBaseData }

constructor TBaseData.Create( AData : TBytes );
begin
  inherited Create;
  FData := AData;
end;

function TBaseData.GetData( const Index : integer ) : integer;
var
  LBitCount : integer;
  LBitOffset : integer;
  LByteOffset : integer;
  LByteIdx : PByte;
  LMask : Byte;
begin
  LBitCount := index and $FF;

  if LBitCount > 32
  then
    raise EArgumentOutOfRangeException.CreateFmt( 'Index %x contains invalid BitWidth %x', [index, LBitCount] );

  LBitOffset := ( index shr 8 ) and $FFFFFF;
  LByteOffset := LBitOffset div 8;
  LBitOffset := LBitOffset - LByteOffset * 8;
  LByteIdx := @FData[LByteOffset];

  { TODO : RangeCheck for LByteOffset }

  if LBitCount > 0
  then
    begin
      LMask := ( 1 shl ( 8 - LBitOffset ) ) - 1;
      Result := ( LByteIdx^ and LMask );
      LBitCount := LBitCount - ( 8 - LBitOffset );
    end
  else
    begin
      Result := 0;
      Exit;
    end;

  while LBitCount >= 8 do
    begin
      Inc( LByteIdx );
      Result := Result shl 8;
      Result := Result or LByteIdx^;
      LBitCount := LBitCount - 8;
    end;

  if LBitCount > 0
  then
    begin
      Inc( LByteIdx );
      Result := Result shl LBitCount;
      LMask := ( 1 shl ( 8 - LBitOffset ) ) - 1;

      Result := Result or ( ( LByteIdx^ shr ( 8 - LBitCount ) ) and LMask );
    end;

end;

end.

Blup 12. Mai 2014 14:36

AW: Bit-Schiebereien
 
Ich vermute in der Methode noch Fehler.
Code:
LBitOffset = 11
LBiCount = 18
Byte       0------- 1------- 2------- 3-------
Bits       01234567 89012345 67890123 45678901
Info       00000000 00010000 11111101 11111000
            $00      $08      $BF     $1F
Erg.       10000111 11101111 11000000 00000000
            $E1      $F7      $03      $00
Ergebnis sollte meiner Meinung nach $0003F7E1 sein, tatsächliches Ergebnis $000117E3.
Scheinbar werden am Anfang und Ende die falschen Bits ausgewählt und auch die Reihenfolge der Byte LSB..MSB stimmt nicht.

Delphi-Quellcode:
const
  FData: array[0..3] of Byte = ($00, $08, $BF, $1F);

function TBaseData.GetData( const Index : integer ) : integer;
var
  LBitCount : integer;
  LBitOffset : integer;
  LByteOffset : integer;
  LByteIdx : PByte;
  LMask : integer;
  LShift: integer;
begin
  LBitCount := Index and $FF;

  if LBitCount > 32
  then
    raise EArgumentOutOfRangeException.CreateFmt( 'Index %x contains invalid BitWidth %x', [index, LBitCount] );

  if LBitCount = 0
  then
    begin
      Result := 0;
      Exit;
    end;

  LBitOffset := ( Index shr 8 ) and $FFFFFF;
  LMask     := $FFFFFFFF shr ( 32 - LBitCount );

  LByteOffset := LBitOffset div 8;
  LBitOffset := LBitOffset mod 8;

  { RangeCheck for LByteOffset }
  if (Length(FData) - LByteOffSet) < ((7 + LBitCount) div 8)
  then
    raise EArgumentOutOfRangeException.CreateFmt( 'Index %x contains invalid BitOffset %x for BitWidth %x', [Index, LBitOffset, LBitCount] );

  LByteIdx := @FData[LByteOffset];

  Result := LByteIdx^ shr LBitOffset;
  LShift := ( 8 - LBitOffset );
  Dec( LBitCount, LShift);
  Inc( LByteIdx );

  while LBitCount > 0 do
    begin
{$R-}
      Result := Result or (Integer(LByteIdx^) shl LShift);
{$R+}
      Inc( LShift, 8);
      Dec( LBitCount, 8);
      Inc( LByteIdx );
    end;

  Result := Result and LMask;
end;

Dejan Vu 12. Mai 2014 16:48

AW: Bit-Schiebereien
 
Sollte man den Offset und den Index nicht lieber doch als zwei Parameter übergeben, anstatt das irgendwie von hinten durch die Brust ins Auge umständlich kodieren zu müssen? So richtig einfach und klar ist das ja nicht.

Blup 13. Mai 2014 08:32

AW: Bit-Schiebereien
 
Der Index liegt scheinbar in den Daten bereits in dieser Form codiert vor.
Das Decodieren könnte man sicher in eine eigene Methode auslagern.
Delphi-Quellcode:
procedure TBaseData.DecodeIndex(const AIndex : DWord; out ABitOffset, ABitCount: DWord);
begin
  ABitOffset := (AIndex shr 8) and $FFFFFF;
  ABitCount := AIndex and $FF;
end;
Als Datentyp würde ich für diese Anwendungsfall Integer generell auch durch vorzeichenlose Typen ersetzen.

Mavarik 13. Mai 2014 11:39

AW: Bit-Schiebereien
 
@Kostas Boh ej....

Schon 38 Nachrichten in diesem Thread und wir rätzeln hier immer noch um den Brei rum...

Gib uns doch einfach mal die Struktur die "da ankommt" und Du hast sicherlich in 2 Min den Record um das aus zu lesen...

Mavarik


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:57 Uhr.
Seite 4 von 4   « Erste     234   

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