Delphi-PRAXiS
Seite 3 von 4     123 4   

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)

himitsu 9. Mai 2014 12:32

AW: Bit-Schiebereien
 
Um wieviele Bit wird denn verschoben?

Bei maximal 8 und verschieben nacht rechts:
- man nimmt ein Byte und verschiebt dessen Bits um X nach rechts
- dazu kommen noch die Bits des vorherrigen Bytes, welche um (8-X) Bits nach links verschoben werden
- das Beides dann mit OR verbinden
- und nun nur noch das Ganze für jedes andere Byte machen (vom rechten Byte, bis zum Linken)


Das läßt sich natürlich noch bis Integer/Int64 aufweiten, wobei man da auf "ungerade" Bytes achten muß, welche keine vollen Interger/Int64 ergeben.

gammatester 9. Mai 2014 12:32

AW: Bit-Schiebereien
 
Zitat:

Zitat von Sir Rufo (Beitrag 1258400)
Wie wäre es mit so einer Lösung
http://stackoverflow.com/questions/2...delphi-records

Würde ich in deinem Fall aber eher als Klasse aufbauen, das Prinzip ist aber gleich

Allerdings sollte man es dann auch richtig machen. 32 Bits in einem WORD zu verwalten, ist doch wohl etwas vermessen (und keiner der Kommentatoren und Upvoter hat's bemerkt).

Dejan Vu 9. Mai 2014 12:39

AW: Bit-Schiebereien
 
Wie wäre es mit einer kleinen Klasse?
Delphi-Quellcode:
Type
  TBits = Class
  public
    constructor Create (data : TBytes);
    function GetBits (BitFrom, BitTo : Integer) : TBytes;
  End;
Und 'GetBits' macht nichts anderes, als die Bytes aus data von Index BitsFrom/8-BitsTo/8 zu kopieren und um BitsFrom mod 8 zu shiften (den Überlauf vom folgenden Byte einmaskieren), und vom letzten Byte müssen die Bits (BitsTo mod 8 - BitsFrom mod 8) weggeschnippelt werden.

Irgendwie so jedenfalls. Mit Papier und Stift sind die Shiftoffsets und das letzte Maskieren doch schnell zusammengezählt.

Alternativ (aber saulangsam) überführt man den Byte-Stream in ein Array of Boolean und bei der Abfrage erzeugt man aus dem Bits dann wieder einen Byte-Stream.

p80286 9. Mai 2014 12:39

AW: Bit-Schiebereien
 
Zitat:

Zitat von gammatester (Beitrag 1258418)
Allerdings sollte man es dann auch richtig machen. 32 Bits in einem WORD zu verwalten, ist doch wohl etwas vermessen (und keiner der Kommentatoren und Upvoter hat's bemerkt).

Die Idee zählt!
Die praktische Umsetzung ist der zweite Schritt.

Gruß
K-H

himitsu 9. Mai 2014 14:02

AW: Bit-Schiebereien
 
Und wenn man groß hinaus will:
Es gibt unzählige Mathebibliotheken für "große" Zahlen, welche man auch verwenden könnte.

Sir Rufo 9. Mai 2014 14:18

AW: Bit-Schiebereien
 
Wie schnell muss dass denn sein?

Ich frage einen 4-Bit Wert aus 2 Bytes
Code:
1111111001111111
genau 1.000.000 ab und das dauert hier so 18ms.

Wenn das schnell genug ist, dann kann ich den Code hier mal reinstellen.

p80286 9. Mai 2014 14:56

AW: Bit-Schiebereien
 
Zitat:

Zitat von Sir Rufo (Beitrag 1258432)
Wenn das schnell genug ist, dann kann ich den Code hier mal reinstellen.

Tu das, ich kann z.Zt. so schlecht tippen:mrgreen:

Gruß
K-H

Sir Rufo 9. Mai 2014 15:52

AW: Bit-Schiebereien
 
Ok, hier der Code.

Durch das Verschieben sollten keine Wert mit mehr als 25bit abgerufen werden, da es sonst zu komischen Ergebnissen kommen kann :)

Es erfolgt keine Überprüfung der Index-Werte ... wer das möchte, der kann sich das ja noch einbauen :)

UPDATE
Ich habe nochmals ca. 2ms weniger (bei 1.000.000 Zugriffen) herausgekitzelt durch eine Änderung in der
Delphi-Quellcode:
GetData
Methode :)
Delphi-Quellcode:
program dp_180297;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.Generics.Collections,
  System.Classes,
  System.SysUtils,
  System.Diagnostics,
  BaseData in 'BaseData.pas',
  BaseDataFactory in 'BaseDataFactory.pas';

type
  TData1 = class( TBaseData )
  public
    property Value1 : Integer index $000604 read GetData; // Offset 6 Bit-Width 4
    property Value2 : Integer index $000010 read GetData; // Offset 0 Bit-Width 16
  end;

procedure ValueCheck( AInstance : TData1 );
begin
  Assert( AInstance.Value1 = 9 );
  Assert( AInstance.Value2 = 65151 );
end;

procedure PerformanceCheck( AInstance : TData1 );
const
  C_ROUNDS = 1000000;
var
  LWatch : TStopwatch;
  LValue : Integer;
  LIdx : Integer;
begin
  LWatch := TStopwatch.StartNew;
  for LIdx := 1 to C_ROUNDS do
    begin
      LValue := AInstance.Value1;
    end;
  LWatch.Stop;

  Writeln( C_ROUNDS, ' Rounds in ', LWatch.ElapsedMilliseconds, 'ms' );
end;

procedure FactoryTest;
var
  LStream : TStream;
  LData : TBytes;
  LInstance : TBaseData;
begin
  TBaseDataFactory.RegisterType( $00, TData1 );

  LStream := TMemoryStream.Create;
  try
    LData := TBytes.Create( $00 { Type } , $02 { Size of Data } , $FE, $7F );
    LStream.Write( LData, Length( LData ) );
    LStream.Seek( 0, soFromBeginning );
    LInstance := TBaseDataFactory.CreateFromStream( LStream );
    try
      ValueCheck( LInstance as TData1 );
    finally
      LInstance.Free;
    end;
  finally
    LStream.Free;
  end;
end;

procedure Main;
var
  LData : TBytes;
  LInstance : TData1;
begin

  LData := TBytes.Create( $FE, $7F );
  // 1111111001111111
  // ......====......
  // Value1 ^ = 1001(bin) = 9(decimal)

  LInstance := TData1.Create( LData );
  try
    ValueCheck( LInstance );
    PerformanceCheck( LInstance );
  finally
    LInstance.Free;
  end;
end;

begin
  ReportMemoryLeaksOnShutdown := True;

  try
    Main;
    FactoryTest;
  except
    on E : Exception do
      Writeln( E.ClassName, ': ', E.Message );
  end;

  ReadLn;

end.
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;
  LBitOffset := ( index shr 8 ) and $FFFF;
  LByteOffset := LBitOffset div 8;
  LBitOffset := LBitOffset - LByteOffset * 8;

  LByteIdx := @FData[LByteOffset];

  LMask := ( 1 shl ( 8 - LBitOffset ) ) - 1;
  Result := ( LByteIdx^ and LMask );
  LBitCount := LBitCount - ( 8 - LBitOffset );

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

  if LBitCount < 0
  then
    Result := Result shr ( -LBitCount );

end;

end.
Delphi-Quellcode:
unit BaseDataFactory;

interface

uses
  System.Generics.Collections,
  System.Classes,
  System.SysUtils,
  BaseData;

type
  TBaseDataClass = class of TBaseData;

  TBaseDataFactory = class
  private
    class var _Types : TDictionary<Byte, TBaseDataClass>;
  protected
    class constructor Create;
    class destructor Destroy;
  public
    class function CreateFromStream( AStream : TStream ) : TBaseData;
    class procedure RegisterType( AType : Byte; AClass : TBaseDataClass );
  end;

implementation

{ TBaseDataFactory }

class constructor TBaseDataFactory.Create;
begin
  _Types := TDictionary<Byte, TBaseDataClass>.Create;
end;

class function TBaseDataFactory.CreateFromStream( AStream : TStream ) : TBaseData;
var
  LType : Byte;
  LSize : Byte;
  LData : TBytes;
  LClass : TBaseDataClass;
begin
  AStream.Read( LType, SizeOf( LType ) );
  AStream.Read( LSize, SizeOf( LSize ) );
  SetLength( LData, LSize );
  AStream.Read( LData, LSize );

  LClass := _Types[LType]; // Bei einem unbekannten Typen wird hier eine Exception geworfen
  Result := LClass.Create( LData );
end;

class destructor TBaseDataFactory.Destroy;
begin
  _Types.Free;
end;

class procedure TBaseDataFactory.RegisterType( AType : Byte; AClass : TBaseDataClass );
begin
  _Types.AddOrSetValue( AType, AClass );
end;

end.

p80286 9. Mai 2014 16:22

AW: Bit-Schiebereien
 
!Danke!:-D

K-H

Sir Rufo 9. Mai 2014 16:29

AW: Bit-Schiebereien
 
Zitat:

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

K-H

Bitte :)

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


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:47 Uhr.
Seite 3 von 4     123 4   

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