Raoni Medinilha
Raoni Medinilha

Reputation: 57

Is there a way to shift left without losing bits in delphi?

Here's the deal, I'm developing a security system and I'm doing some bit scrambling using bitwise operations. Using 4 bits just to illustrate, supose I have 1001 and I wish to shift left. This would leave me with 0010 since the right-most bit would be lost. What I wanted to do was to shift left and right without losing any bits.

Upvotes: 0

Views: 1057

Answers (1)

David Heffernan
David Heffernan

Reputation: 613262

You might choose to use rotate rather than shift. That preserves all the bits. If you wish to use an intermediate value that is the result of a shift, perform both a rotate and a shift. Keep track of the value returned by the rotate, but use the value returned by the shift. This question provides various implementations of rotate operations: RolDWord Implementation in Delphi (both 32 and 64 bit)?

Another option is to never modify the original value. Instead just keep track of the cumulative shift, and when a value is required, return it.

type
  TLosslessShifter = record
  private
    FData: Cardinal;
    FShift: Integer;
    function GetValue: Cardinal;
  public
    class function New(Data: Cardinal): TLosslessShifter; static;
    procedure Shift(ShiftIncrement: Integer);
    property Value: Cardinal read GetValue;
  end;

class function TLosslessShifter.New(Data: Cardinal): TLosslessShifter;
begin
  Result.FData := Data;
  Result.FShift := 0;
end;

procedure TLosslessShifter.Shift(ShiftIncrement: Integer);
begin
  inc(FShift, ShiftIncrement);
end;

function TLosslessShifter.GetValue: Cardinal;
begin
  if FShift > 0 then
    Result := FData shr FShift
  else
    Result := FData shl -FShift;
end;

Some example usage and output:

var
  Shifter: TLosslessShifter;
....
Shifter := TLosslessShifter.New(8);
Shifter.Shift(-1);
Writeln(Shifter.Value);
Shifter.Shift(5);
Writeln(Shifter.Value);
Shifter.Shift(-4);
Writeln(Shifter.Value);

Output:

16
0
8

Upvotes: 3

Related Questions