B4J Question Bit manipulation in integer

Jeanc161

Member
Licensed User
Longtime User
Hi i want to set or reset a bit of an integer and read back that bit in the same integer to tell me if the bit is set or not set

Ex: i want to set the bit 1 and 7 of an integer of 0X0 does not matter what the value of the initial integer is but as a start it will be to 0 but when reading a value from a file that integer will be set to whatever the value that correspond to bit 1 and 7 bit set ,
I want to be able to pass that number to a bit reader that will tell me if the bit 1 or the bit 7 is set or it can be both 1 and 7.
I tried with Bit.Or it set the integer value ok but i can't seem to read the bit setting as it return always false

On that specific integer i have up to 12 bits to set or not that correspond to some value when it is interpreted in B4A, B4I, or B4J
it could have more then 1 position to be set but mostly 1 or 2 bit will be set at the same time.

Here is some code that i use it is only for testing

Can someone help me with that i don't know what i'm doing wrong to get it work

Test set and read the bit of an integer
bit set and read:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Public bitString As Long = 0x0   ' this value will be stored in a file and the value should correspond to the bits set in that integer
    Public jo As JavaObject
    Private Label1 As Label
    Private TextField1 As TextField
    Private Button2 As Button
    Private Label2 As Label
End Sub

Public Sub Initialize
    
'    B4XPages.GetManager.LogEvents = True
    jo = Me
End Sub



Private Sub Button1_Click    this set the bit by index value ex:1 or 7 or both
    Dim indx As long
        indx = TextField1.Text  ' either 1 or 7 or other bit number
        bitString = setBit(indx,bitString)
        Label2.Text = bitString
    
End Sub

Private Sub Button2_Click      ' this read the value of a specific bit in the integer
    Dim Result As Boolean
    Dim Msg As String
    Dim indx As long
        indx = TextField1.Text
        Result = readBit(indx,bitString)
        Log("Result of bit read at index:" & TextField1.Text & "  " & Result)
        Label2.Text = bitString
        If Result = True Then   
            Msg = "The bit is set"
        Else
            Msg = "The bit is not set"   
        End If
        
        xui.MsgboxAsync(Msg, "BITS")
End Sub


public Sub AndLong (N1 As Long, N2 As Long) As Long
    Return jo.RunMethod("andLong", Array(N1, N2))
End Sub

public Sub OrLong (N1 As Long, N2 As Long) As Long
    Return jo.RunMethod("orLong", Array(N1, N2))
End Sub

public Sub ShiftLeftLong (N1 As Long, Index As Int) As Long
    Return jo.RunMethod("shiftLeftLong",Array(N1,Index))
End Sub

Sub GetBitLong (bstr As Long, index As Int) As Boolean
    Log("reading:" & bstr)
    Dim t As Long = ShiftLeftLong(bstr,index)
    Return AndLong(bstr,t) = t
End Sub
 

Jeanc161

Member
Licensed User
Longtime User
Hi
I look at the solution to using B4xCollection and it does not meet the requirement needed, shure it set the bit of one byte "00000000" but it does not set both ex: need to set bit 1 and bit 4 or bit 1 and bit 5 at the same time, so i don't know if there is something that can set the 2 bits simultanously of a byte, but even then i need 12 bytes to set all the combinations of flags that i need to set.

Normally when using VB6 i use a string with the number of "0" and use the keyword Mid not the function mid as for example

So i don't know if the java language have an equivalent for the mid= in it's language, i try different things using the substring2 but it is only goog for reading since it is a function it always require a parameter wich is not possible.

So if anybody have a solution for this either using the bit.Or and stuff to set 2 bit on the same integer using either a byte or an integer

Please.. Please let me know asap i'm am block by this and can't find a quick solution after 3 or 4 days of testing different method to acheive the same result

Thanks u all

B4X:
Dim bitString as string = "000000000000"
' Then to set the byte 5 for example

 bitString = setByte(5,bitString)
 ' To read the byte 5 of bitString'
 log(readByte(5,bitString))
  ' should display 1'
 
Function readByte(indx, bitStr) 
   readByte = Mid(bitStr,Indx,1)
End function

Function setByte(indx,bitStr)
   Mid(bitStr,indx,1) = "1"
   setByte = bitStr   
End function
 
Upvote 0

emexes

Expert
Licensed User
Please.. Please let me know asap i'm am block by this and can't find a quick solution after 3 or 4 days of testing different method to acheive the same result

Well, because you said please twice :) this is how I'd do it:

B4X:
Dim bitstring As Int = 0x8001    'arbitrary starting value
Log(bitstring & " = " & Bit.ToBinaryString(bitstring) & " before bits set")

Dim Bit4 As Int = Bit.ShiftLeft(1, 4)    'ie 2^4 or just 16
Dim Bit7 As Int = Bit.ShiftLeft(1, 7)    'ie 2^7 or just 128

bitstring = Bit.Or(bitstring, Bit4 + Bit7)    'adding bits is same as or-ing bits, as long as bits don't overlap ie no same bit more than once
Log(bitstring & " = " & Bit.ToBinaryString(bitstring) & " after bits set")

bitstring = Bit.And(bitstring, Bit.Not(Bit4 + Bit7))
Log(bitstring & " = " & Bit.ToBinaryString(bitstring) & " before bits cleared")

1643223127626.png
 
Last edited:
Upvote 0

Jeanc161

Member
Licensed User
Longtime User
That is nice but got one more question about you idea after the bits are set how do you manage to read it back and get the bits that are set so i can separate those two bits from the integer value,
I need to test each bits to determine the value as to know if bit 4 is set then assign a value to another variable that bit 4 represent and same for bit 7
I know these bit will only be set once when i compile the value of each bits and this value will be stored in a file with other infos. But when i reload the value of the integer from the file in other app i need to determine what each bit is set so i can define the group and sub group that these bit represents.
I did not create the sub that will read these value and set the differents group to wich these bit are set when reading.

AS for example assume the bit 4 and 7 are set in that integer, i will have to test each bit starting from bit 1 to bit 12 and if i found a bit that is set, i will attribute a value to another variable to wich each bit represent on that integer.

The method you describe work very well i try it on a test program but right now i don't know how to read it back bit by bit.

Thanks for the method.
If you know how to read it back please let me know, i have to finish this before i go on with the reading and assigning each bit to it's proper group or sub-group that it represent.

PS The sub that attribute the value to each group is in B4J the sub that will read it back is in b4A or B4I (thanks)
 
Upvote 0

emexes

Expert
Licensed User
i will have to test each bit starting from bit 1 to bit 12

Just to clarify: do you call the least-significant bit (ie, the right-most bit) bit 0 or bit 1 ?

Things work out way easier if we call it bit 0 eg bit n has a value of 2^n.

I am going to assume that you are meaning to test the lower 12 bits of an integer, ie bit 0 to bit 11.
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
B4X:
Dim StatusRegister As Int = 0x0314    'arbitrary example test value

Log("The test value is " & StatusRegister & " = " & Bit.ToBinaryString(StatusRegister) & " binary)")

Log("This way works best for checking single bits")
If Bit.And(StatusRegister,     1) <> 0 Then Log("Bit 0 is set")    'or 0x001
If Bit.And(StatusRegister,     2) <> 0 Then Log("Bit 1 is set")    'or 0x002
If Bit.And(StatusRegister,     4) <> 0 Then Log("Bit 2 is set")    'or 0x004
If Bit.And(StatusRegister,     8) <> 0 Then Log("Bit 3 is set")    'or 0x008
If Bit.And(StatusRegister,    16) <> 0 Then Log("Bit 4 is set")    'or 0x010
If Bit.And(StatusRegister,    32) <> 0 Then Log("Bit 5 is set")    'or 0x020
If Bit.And(StatusRegister,    64) <> 0 Then Log("Bit 6 is set")    'or 0x040
If Bit.And(StatusRegister, 0x080) <> 0 Then Log("Bit 7 is set")    'or 128
If Bit.And(StatusRegister, 0x100) <> 0 Then Log("Bit 8 is set")    'or 256
If Bit.And(StatusRegister, 0x200) <> 0 Then Log("Bit 9 is set")    'or 512
If Bit.And(StatusRegister,  1024) <> 0 Then Log("Bit 10 is set")   'or 0x400
If Bit.And(StatusRegister,  2048) <> 0 Then Log("Bit 11 is set")   'or 0x800

Log("This way works best for checking bits in sequence starting from the 'smallest'/rightmost bit")
 
Dim BitValue As Int = 1    'start from least-significant bit ie bit 0
For BitNumber = 0 To 11
    If Bit.And(StatusRegister, BitValue) <> 0 Then
        Log("Bit " & BitNumber & " (value " & BitValue & ") is set")
    End If
    BitValue = Bit.ShiftLeft(BitValue, 1)
Next

1643243921434.png
 
Upvote 0

Jeanc161

Member
Licensed User
Longtime User
well after many struggles i finally made it, i can read from bit 1 to 14 the bit 15 is already set by the initial value of 0x8000 "10000000000000000"
the bit 15 as i said is set to 1 .
So i convert the binary number to strings, and setup a sub that read the string returned by it's index. But the funny thing you have to reverse the index number since 1 is the 14 byte of the string. so i add (15 - index) and it give me the right location to search for and returned the right bit to look for, and since i use the bit.or the other value of the integer remain and can simply add another bit to set with the index number, so i can have multiples bit that i can set giving me the flexibility that i needed.

I did not use a bit.or to find the bit in binary, but instead use the string representation of the integer, thanks to Bit.ToBinaryString(Integer) that return a string of 0 and 1
if you are interested to see the code that i finally will use i can show you in another post, just ask for it and i will show you the method i use.

Thanks to emexes for it example it took me a while to understand everything but finally that works and thats all that matter.

Thank you for your help emexes, you saved my day and a lot of lost time.
 
Upvote 0

Jeanc161

Member
Licensed User
Longtime User
Here a sample of the code that i use

B4X:
Sub Class_Globals
    
    Public bitS(16) As Int        ' need that for quick access'
    Private Bits1 As Int = Bit.ShiftLeft(1, 1)
    Private Bits2 As Int = Bit.ShiftLeft(1, 2)
    Private Bits3 As Int = Bit.ShiftLeft(1 ,3)
    Private Bits4 As Int = Bit.ShiftLeft(1, 4)    'ie 2^4 or just 16
    Private Bits5 As Int = Bit.ShiftLeft(1, 5)
    Private Bits6 As Int = Bit.ShiftLeft(1, 6)
    Private Bits7 As Int = Bit.ShiftLeft(1, 7)    'ie 2^7 or just 128
    Private Bits8 As Int = Bit.ShiftLeft(1, 8)
    Private Bits9 As Int = Bit.ShiftLeft(1, 9)
    Private Bits10 As Int = Bit.ShiftLeft(1,10)
    Private Bits11 As Int = Bit.ShiftLeft(1,11)
    Private Bits12 As Int = Bit.ShiftLeft(1,12)
    Private Bits13 As Int = Bit.ShiftLeft(1,13)
    Private Bits14 As Int = Bit.ShiftLeft(1,14)
    Private Bits15 As Int = Bit.ShiftLeft(1,15)
End sub

Private Sub B4XPage_Created (Root1 As B4XView)
    bitS(1) = Bits1 : bitS(2) = Bits2 : bitS(3) = Bits3 : bitS(4) = Bits4 : bitS(5) = Bits5 : bitS(6) = Bits6
    bitS(7) = Bits7 : bitS(8) = Bits8 : bitS(9) = Bits9 : bitS(10) = Bits10 : bitS(11) = Bits11 : bitS(12) = Bits12
    bitS(13) = Bits13 : bitS(14) = Bits14 : bitS(15) = Bits15
End sub

Private Sub Button1_Click         ' set the bit by index 1-14'
    Dim indx As Int
        indx = TextField1.Text
        bitString = SetBit(bitString,indx,True)
        DisplayBits(bitString)
End Sub

Private Sub Button2_Click
    Dim Result As Boolean
    Dim Msg As String
    Dim indx As Int
        indx = TextField1.Text        ' index to test for 1-14'
        Result = getByte(bitString,indx)
        DisplayBits(bitString)
        Log("Result of bit read at index:" & TextField1.Text & "  " & Result)
        If Result = True Then   
            Msg = "The bit is set"
        Else
            Msg = "The bit is not set"   
        End If
        xui.MsgboxAsync(Msg, "BITS")
End Sub

Sub SetBit(b As Int, index As Int, on As Boolean) As Int
    If index < 0 Then index = 0
       Dim bitValue As Int = bitS(index)
    If on Then
       b = Bit.Or(b, bitValue)   
    Else
       b = Bit.Or(b, Bit.Not(bitValue))
    End If     
    Return b
End Sub


Sub getByte(bt As Int,index As Int) As Boolean
    Dim bstr As String = Bit.ToBinaryString(bt)
    Dim b As String
    Dim indx As Int
        indx = 15 - index
    'index = index - 1
    If indx < 0 Then
        indx = 0
    End If
Try
        If bstr.SubString2(indx,indx+1) = "0" Then
            Return False
        else if bstr.SubString2(indx,indx+1) = "1" Then
            Return True   
        End If
    Catch
        Log(LastException)
    End Try
End Sub

Sub DisplayBits(Bt As Int)
    ' display the value of each bits
    Dim nStr As String = ""
    Dim on As Boolean
    Dim bitValue As Int = Bt
    Dim bitStr As String = Bit.ToBinaryString(Bt)
    Log("**************************")
    Log("Binary format")
    Log(bitStr)
    Label2.Text = bitStr
End Sub

Sub clearBits()        ' clear all the bits to 0 but not the first bit
    bitString = 0x8000
    DisplayBits(bitString)
End Sub

This code is not the perfect solution but it does everything i need and is compatible with B4A, B4I and B4J so yeaaaaaa.

Thanks for the sample code emexes
 
Upvote 0

emexes

Expert
Licensed User
This code is not the perfect solution but it does everything i need and is compatible with B4A, B4I and B4J so yeaaaaaa.

... does almost everything ... I think this routine is going to disappoint you:

B4X:
Sub SetBit(b As Int, index As Int, on As Boolean) As Int
    If index < 0 Then index = 0
       Dim bitValue As Int = bitS(index)
    If on Then
       b = Bit.Or(b, bitValue)
    Else
       b = Bit.Or(b, Bit.Not(bitValue))
    End If
    Return b
End Sub

until you do this:

B4X:
    If on Then
       b = Bit.Or(b, bitValue)
    Else
       '''b = Bit.Or(b, Bit.Not(bitValue))    close, but no cigar - rather than clearing indexed bit, it will set all bits except indexed bit
       b = Bit.And(b, Bit.Not(bitValue))
    End If
 
Last edited:
Upvote 0

Jeanc161

Member
Licensed User
Longtime User
Thanks for the warning, i change it to bit.and and it works like a charm now, i was busy inserting the subs and data that i created and tested, and now the reading sub does it job and return me the right values for each bit that are set, so that i can assign a value to my 2 variables that i need to define the group and sub group.

Thansk for your help, but now it's coding time, finally will be able to finish the compiler and modify my code in my app.

Like you said NEVER GIVE UP !
 
Upvote 0
Top