![]() |
AW: Bit-Schiebereien
Zitat:
Aber da wir immer noch nicht die Struktur kennen... Mavarik |
AW: Bit-Schiebereien
Zitat:
Aber die Chance ist recht groß, daß es beim Create knallt. |
AW: Bit-Schiebereien
Zitat:
Delphi-Quellcode:
noch nicht aufgefallen.
TDictionary
Kannst du das mal erläutern? |
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. |
AW: Bit-Schiebereien
Ich vermute in der Methode noch Fehler.
Code:
Ergebnis sollte meiner Meinung nach $0003F7E1 sein, tatsächliches Ergebnis $000117E3.
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 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; |
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.
|
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:
Als Datentyp würde ich für diese Anwendungsfall Integer generell auch durch vorzeichenlose Typen ersetzen.
procedure TBaseData.DecodeIndex(const AIndex : DWord; out ABitOffset, ABitCount: DWord);
begin ABitOffset := (AIndex shr 8) and $FFFFFF; ABitCount := AIndex and $FF; end; |
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 06:56 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz