Reputation: 57
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
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