Samashki95 Samashki95 - 6 months ago 53
Java Question

Delphi SetBit-function and TBitRange- type in Java

I have to implement the following Delphi function in Java, but anyway the type TBitRange is confusing me. Is there any alternative for this in Java?
Maybe could also anyone explain what this function is doing exactly.

Thanks.

const
BitsPerByte = 8;
BitsPerInteger = SizeOf(Integer) * BitsPerByte;

type
TBitRange = Byte;

function SetBit(const Value: Integer; const Bit: TBitRange): Integer;
begin
Result := Value or (1 shl (Bit mod BitsPerInteger));
end;


In my Java I implemented this setBit-function as:

static int bitsPerInteger = Integer.SIZE;
public int setBit(int value, byte bit)
{
int result = value | (1 << (bit % bitsPerInteger));
return result;
}


If I understood in correctly, this function returns the copy of value with the bit at position bit set. The bitsPerInteger variable is Integer.SIZE and is equal to 32. For the test I created two variables: byte bits = 0x34; it's equal 52 as Integer and int value = 4;. The instruction bits % bitsPerInteger; delievers in this case 20 and value | (1 << (bits % bitsPerInteger)) sets the 20th bit of value to 1 and it's equal then to 1048576. So I handed over these two variables as parameters and got then 1048576. Is it right so?

Why its needed to hand over a variable with type Byte as parameter for bit-position and then through mod -operation get the actually bit-position in bit-String of parameter value?. Could we not use an Integer to indicate the bit-position in value?

Answer

Ideally TBitRange should be a subrange, e.g.:

type
  TBitRange = 0..31;

The subrange gets enforced at compile time.
Java does not have subranges, so there is no equivalent.

You can declare the function as follows:

public static int SetBit(final int Value, final byte Bit)
{
    assert bit >= 0;
    assert bit <= 31;   
    final int shift = 1 << Bit;
    return Value | shift;
}

Unfortunately the assert is only checked at runtime.

However in your earlier deleted question you defined TBitRange as:

type
  TBitRange = Byte; 

The byte type in Java is signed, whereas the byte type in Delphi is unsigned. There is no unsigned 8 bit int in Java. For the purpose of the question though a signed Java byte will work just fine.

About shl
Delphi's shl/shr follows x86 sematics and is thus wrapped around at 32 for integers. For this reason the mod BitsPerInteger part is pointless. The language already performs this operation as per its specification (i.e. someint shl 32 is a no-op).

Java does the same thing so in Java the mod is also not needed.

what is this function doing exactly?

Just like it says on the label: it sets a bit.
An integer is a 32-bit type.
This means that there are 32 bits (on/off switches aka booleans) inside the variable.
These are numbered from 0 to 31.
If you want to conserve space you can use this fact to store 32 booleans in a single integer, instead of having to use 32 variables. This squeezes 32 bytes into 4 bytes; an 8x reduction.
In Delphi we usually utilize a set of ... for this. Java does not have sets, so you'll have to resort to using a bitfield instead.

A bitfield is really a compressed array of boolean, but because there is no array syntax for bitfields you'll have to use functions instead.

BoolArray[8]:= true -> BitField:= SetBit(BitField,8);
if BoolArray[8] then ... -> if GetBit(BitField,8) then ...  

Obviously in Delphi you could emulate this using properties:

TBitField = record
private
  FStorage: integer;
  function GetBit(Index: TBitRange): boolean;
  procedure SetBit(Index: TBitRange; const Value: boolean);
public
  property IsTrue[Index: TBitRange]: boolean read GetBit write SetBit;
end;

Properties is another thing Java does not have, so in Java it is really impossible to do this fake array trick.