1 Attachment(s)
If lngStyle And mcWSVISIBLE Then
If lngStyle And mcWSVISIBLE Then
If lngStyle And mcWSVISIBLE Then
Some notes, codings etc. in support of some other posts
https://eileenslounge.com/viewtopic....321979#p321979 https://eileenslounge.com/viewtopic.php?f=30&t=41610
https://www.excelfox.com/forum/showt...l=1#post249016
Introduction
A code line from the last post
, If lngStyle And mcWSVISIBLE Then
What’s going on? – Hans told me …. The number is looked at by VBA in its binary representation form, and each corresponding Bit at the same horizontal position for the two numbers is compared. This is referred to as bitwise AND of the binary representation of the numbers.
In simple terms, If at any position both are 1 , then the result will be true…..
It all started here:
I had some strange results that I did not understand. It boiled down to some code lines such as this returning True
If -1811939328 And 268435456 Then
, whilst similar such as this returning False
If -2046820352 And 268435456 Then
At first glance there is no thing obvious to see to explain the difference in behaviour in the two examples
So, because ExcelFox is the adult thinking man’s forum, we are going to have a good look at it.
Knowing the answer, or appearing to be close to knowing it, suggests we want initially to get those two decimals into some String like " 0 1 " representation of a number( Binary computer stuff " 0 0 0 1 0 1 1 0 1 " )
A couple of points to consider
_(i) A string type representation of a lot of 0s and 1s is a good idea so that we don’t have problems with things like leading 0s vanishing when Excel or VBA messes with the format of a number we may write: In binary computer things the number will have typically some fixed character length, so we should not mess with that, or let Excel or VBA mess with it
_(ii) The first Bit/first position is always reserved for the sign character, (which is 1 for a negative number, and that sort of leads to the phenomena that Anding two negative numbers always results in a True. But it is not quite so straight forward always.
It's an artefact, perhaps, of both how computers store negative numbers and the bit wise way that the VBA And works.
The following function to convert a decimal to binary is useful to know about and understand, but bare in mind that solving the main issue ended up being a bit more involved.
A simple function to get the string like binary 0s and 1s representation of a number.
The basic idea: (To keep it simple initially in this first summary, we will not concern ourselves directly with the actual unbar of digits in the binary string of 1s and 0s )
It’s basically all based on the school maths way of converting a decimal to binary…. Take the decimal number and divide it by a number got from a high power of 2;
__ If that division comes out >= 1 , then you have your first binary digit, starting from the left of 1; then you subtract that number which was the high power of 2 from the decimal number , so the decimal number under consideration is now smaller
__ Else when that division comes out < 1 , then you have your first binary digit of 0 starting from the left. You leave the decimal number at the size it is.
Now you do the same again using the next power of 2 down as the denominator to get the next binary digit to the right. Eventually you are down to (2 ^0) to get the last binary digit at the right
The actual implementation in the coding.
We decide on some length limit for the string. For now, based on an initial quick empirical look and guess, I will go for up to 30 powers of 2, ( (2 ^ N) = (2 ^ 30) ). I might change that later based on experience. A big one initially will hopefully catch numbers as big as we have. This means the string length will be 32 characters, as in the string like binary 0s and 1s representation we have (2 ^ 0) at the right, (2 ^ 30) at the left, and also an extra sign bit included to be the **first left character. ( ** As it turns out it is not quite as simple as that )
A simple function can be one that builds the string….
, first with a 0 or 1 is added to the string depending on if the decimal number being converted is negative or positive
, then we successively divide the number by (2 ^ N) where N goes from 30 to 0.
__ If the result of the division results in 1 or 1 and a fraction more, we add** ( ** add as in including another character, via a & "1" not maths add + ) a "1" to the string, and reduce the decimal number by that used (2 ^ N) , before moving to the next N.
__ Else the division results in less than 1, then we add a 0, (and do not reduce the decimal value)
, then move on to the next N
Code:
Sub TestNumberInBinary()
Debug.Print NumberInBinary(9) ' 00000000000000000000000000001001
Debug.Print NumberInBinary(268435456) ' 00010000000000000000000000000000
End Sub
Public Function NumberInBinary(ByVal DecNumber As Long) As String
Rem 1 A negative number in a computer binary representation has a 1 at the first character position
Let NumberInBinary = IIf(DecNumber < 0, "1", "0")
Rem 2 we successively divide the number by (2 ^ N) where N goes from 30 to 0. If the result of the division results in 1 or 1 and a fraction more, we add** ( ** add as in including another character, not maths add ) a 1 to the string, and reduce the decimal number by that (2 ^ N) before moving to the next N. If the division resilts in less than 1, we add a 0, then move on to the next N Divide the decimal number by 2 to the power of N, with N geting smaller. Every tine the resulting number is equal or bigger than 1 the binary bit would be 1 and the decimal number we reduce by that 2 to the N, and keep going
Dim N As Long
For N = 30 To 0 Step -1 ' 30 seems to be the limit before something is too big
If DecNumber / (2 ^ N) >= 1 Then
Let NumberInBinary = NumberInBinary & "1"
Let DecNumber = DecNumber - (2 ^ N)
Else
Let NumberInBinary = NumberInBinary & "0"
End If
Next N
End Function
A function to mimic the behaviour of the VBA And with numbers is very easy.
Simply
_ convert the two decimal numbers to a string in the form of the computer binary 0s and 1s representation, (using for example the function I did above)
_ then starting from the left compare the characters in the corresponding position in the two strings. As soon as you get a 1 in both , you make the functions returned output as True and exit the function, otherwise the function returns false if you never get a pair of 1s at the same horizontal position
Code:
Public Function NumbersInVBAIf_And_Then(ByVal Dec1 As Long, Dec2 As Long) As Boolean
Rem 1 the two decimal numbers to a string in the form of the computer binary 0s and 1s representation
Dim Bin1 As String, Bin2 As String ' String representation helps prevent loosing leading 0's
Let Bin1 = NumberInBinary(Dec1): Bin2 = NumberInBinary(Dec2)
Rem 2 starting from the left compare the characters in the corresponding position in the two strings. As soon as you get a 1 in both , you make the functions returned output as True and exit the function, otherwise the function returns false if you never get a pair of 1s
Dim TPwr As Long
For TPwr = 1 To 32 Step 1
If Mid(Bin1, TPwr, 1) = 1 And Mid(Bin2, TPwr, 1) = 1 Then Let NumbersInVBAIf_And_Then = True: Exit Function
Next TPwr
End Function
Conclusions, … Oh dear :(
I thought it was too good to be true. It did tons of tests, my coding is sound, and definitely does what I think it should with all data extremes
It doesn’t’ get the right bloody results though: ….Compare… as before, column D ( which effectively does what the main full codng does ) which gets the correct results.
Based on everything so far, this is the test coding to get results in column E
Code:
Sub TryMyFuncsNumberInBinaryNumbersInVBAIf_And_Then()
Range("E2:E20").Clear
Dim Rw As Long, arrRws() As Variant: Let arrRws() = Range("A1:C20").Value
For Rw = 2 To 20
Let Range("E" & Rw) = NumbersInVBAIf_And_Then(arrRws(Rw, 2), arrRws(Rw, 3))
Next Rw
End Sub
The results, however, speak for themselves..
https://i.postimg.cc/2jxYmcbH/Bollox.jpg
Attachment 6120 https://i.postimg.cc/2jxYmcbH/Bollox.jpg
Bollox
.... continued in next post
2’s Compliment Function Decimal To Binary conversion, section for negative Decimal numbers
2’s Compliment Function Decimal To Binary conversion, section for negative Decimal numbers
'== Rem 2 == 2's complement Negative Binary number from decimal ==========================
The coding is not written particularly efficient. It’s written in a way to help understand more clearly what is going on for learning purposes and better later revision
'2a) I see no fundamental reason not to work on the negative decimal number, but for clarity I make the decimal number to its absolute (positive) value here. (A sign change would do just as well here)
'2b) This section is once again possibly an inefficient thing to do, but for clarity, I find the power of 2 number ( value of N ) at which (2 ^ N) is equal or bigger than the (now considered as positive) decimal number. In effect we know the position where in simple normal binary the first 1 would go looking left to right, in other words we effectively have this value, ( at the (2 ^ 6) ) , when considering normal binary values
9 8 7 6 5 4 3 2 1 0 ---- N from (2 ^ N)
0 0 0 1 1 0 1 1 0 0 ---- Normal binary number
For the above example, I am saying we are at the left first digit of a final binary number that , as example, would look in normal binary, if written as one might manually in maths class at school, as this
1 1 0 1 1 0 0
'2c) This section is just the classic school maths, as we did before a few times, of converting a decimal to a binary, just back to front with a 0 put where you would have put a 1 and visa versa. This is because, considering the last example again, we want to have the "flip" of that, so we actually want
0 0 1 0 0 1 1
'2c)(i) Using the above example again, I am at the start of constructing the string variable to be returned by the function, NumberInBinary2sCompliment, or rather , at the first significant part, effectively what would be the first 1 in normal binary. But, in actual fact, I want the "flip" of it. Rather than construct it and then flip it, which would be talking inefficiency a bit far, I construct it on the flip side as it where. So I add my first character to the string. It will be the flip of 1, so it will be 0
'2c)(ii)The first binary digit was known so added above, as was the reduction of the decimal value by the (2 ^ N) value. So now we continue the looping for the rest
I am using a Do While Loop for no particular reason, rather than a For Next Loop, - its just slightly simpler than having to have a variable, such as NN for the next N to use in a line like For N = NN To 0 Step -1 . But basically I do now the classic progression in school maths that we did a few times already, just back to front(flipped), i.e., with a 0 put where you would put a 1 and visa versa
So at the end of this section I have my final flipped binary number for the decimal value. In other words I have the exact flip of the normal binary for the decimal number.
'2d) I have the flip, so I now want to add a 1 in binary
I loop, effectively going from right to left along the binary number. Because of the way I add a 1 in binary, I effectively am looking for the next " empty" , that is to say 0 , in which to "dump" this 1. If however, I find a 1, I must change that 1 to a 0, and try again at the next left position. I am finished in this For Next loop as soon as I have "got rid" of the 1
At this point I sort of, have my final 2s Compliment binary number. But generally, a binary in computer workings has a fixed length , so that a normal number would then have a lot of 0s added to the left, or as many as needed to get the length, probably 32 I would guess. In this negative value 2s compliment, the basic idea is the same, except that 1s are added to the left.
'2e) This effectively adds 1s to the left to get the full digit size of a typical computer number ( remember the way I chose to do this , means that sections '2b) and '2c) may get me a small number of digits for a small decimal number, something like 1 1 0 1 1 0 0 , rather than a more typical in computing thing where unused digits are at 0, (for positive binary numbers ), like 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0
So, three simple lines:
_ I make a variable of the length finally wanted. (The characters I use is irrelevant!!°)
_ The RSet statement puts my current 2s compliment binary number at the right of the made string, ( and the rest of the characters become spaces, - !!° hence the characters I used to make the string was irrelevant )
_ The spaces are changed to 1s
That’s it!, or rather this is it below – the full working function Function NumberInBinary2sCompliment(ByVal DecNumber As Long) As String
The over next post details a quick test of the function
Code:
' https://www.excelfox.com/forum/showthread.php/2989-Rough-Notes-and-posts-to-be-referenced-from-elsewhere-on-VBA-Windows-API?p=24922&viewfull=1#post24922
Public Function NumberInBinary2sCompliment(ByVal DecNumber As Long) As String
If Not DecNumber < 0 Then
Rem 1 Positive decimal number
Let NumberInBinary2sCompliment = NumberInBinary2sCompliment & "0" ' The first digit ( or last 32th if you prefer ) is included, 0 is for a positive number
' Here we go again with the classic school maths way of converting a decimal number to binary
Dim N As Long ' N is effectively the power of two at any time
For N = 30 To 0 Step -1 ' We can think of this as looping from left to right, down the power of 2 values. 30 seems to be the limit before something is too big
If DecNumber / (2 ^ N) >= 1 Then ' We need a 1 in the position, for this power of 2
Let NumberInBinary2sCompliment = NumberInBinary2sCompliment & "1" ' putting effectively a 1 in the position, for this power of 2
Let DecNumber = DecNumber - (2 ^ N) ' We have effectively accounted for an amount equal to this power of 2, so the decimal number we will further investigate must effectively be reduced
Else ' We cant effectively eat up am amount from the decimal of this value of power 2 as the decimal total is smaller, so the binary string needs a 0 at this position
Let NumberInBinary2sCompliment = NumberInBinary2sCompliment & "0"
End If
Next N ' We effectively go to the next power of 2 down
Exit Function ' We are finished here for a positive decimal number
Else ' The case of a negative decimal number
'== Rem 2 == 2's 2's complement Negative Binary number from decimal ===============================
'2a)
Let DecNumber = Abs(DecNumber) ' We know we are negative, that will be taken care of automatically later as a result of making all unused digits 1. I could probably fiddle the maths below to work on negative numbers, but just for lazy comvenmience I will make the decimal number positive here
'2b) This bit brings me
Let N = 30 ' Back to the start left of our powers of 2
Dim Frac As Double: Let Frac = DecNumber / (2 ^ N)
Do While Frac < 1 ' We want to get to the number of digits needed for the number when in normal binary representation. Mostly lazy convenience I think so as to see a nice smaller amount of 0s and 1s when testing/ debugging
Let N = N - 1
Let Frac = DecNumber / (2 ^ N)
Loop ' While Frac < 1 ' I am effectibely working from left to right along the power to 2 range,
'2c) The classic school maths of converting a decimal to a binary, just back to front (fliped) with a 0 put where you would put a 1 and visa versa
'2c)(i) In normal binary I know I want my first 1,
Let NumberInBinary2sCompliment = "0" ' so we have as many digits as we need and we know the first digit would be 1 in binary , but in 2sCompliment it will be "0"
Let DecNumber = DecNumber - (2 ^ N) ' this and the last line are effectively the first use of the If section in the school maths way of converting a decimal to a binary
'2c)(ii)
Do While N <> 0
Let N = N - 1
If DecNumber / (2 ^ N) >= 1 Then ' The next 3 code lines are the classic progression in school maths, just back to front(flipped) with a 0 put where you would put a 1 and visa versa
Let NumberInBinary2sCompliment = NumberInBinary2sCompliment & "0"
Let DecNumber = DecNumber - (2 ^ N)
Else
Let NumberInBinary2sCompliment = NumberInBinary2sCompliment & "1"
End If
Loop ' While N <> 0
'2d) add 1 in binary maths
Dim ToAdd As Long: Let ToAdd = 1 ' I have 1 and I need to get rid of it. (##I don't need the variable, I could use just a 1 in place of it) I work from the right of the binary number and effectively dump it on the first position with a 0 If the positon is 1 already, I must changer that to 0 , - a bit like reaching 10 in normal maths, where you leave aa 0 then carry the 1 over to the next column/digit on the left, then try again to get rid of the 1
For N = Len(NumberInBinary2sCompliment) To 1 Step -1 ' Effectively going from right to left along the binary number
If Mid(NumberInBinary2sCompliment, N, 1) = 0 Then ' I can dump my 1 here then i am finished with this section
Mid(NumberInBinary2sCompliment, N, 1) = ToAdd ' ##I don't need the variable, I could use just a 1 in place of it
Let ToAdd = 0 ' I don't need this as I am finished here.
Exit For ' As soon as we got rid of the 1 to add, we are finished
Else ' I must have come acros a 1
Mid(NumberInBinary2sCompliment, N, 1) = 0 ' I hit a 1, so 1+1 in binary is like reaching 10 in normal maths, where you leave aa 0 then carry the 1 over to the next column/digit on the left, then try again to get rid of the 1
End If
Next N ' Go to next character to the left to see if it is 0 so that I can get rid of the 1 ToAdd
'2e) ' my final binary number could be short or long at this point depending on the size of the original decimal number. This ssection
Dim BiffaBin As String: Let BiffaBin = String$(32, " ") ' Make a string of the length I want, (The characters I use is irrelevant!!)
RSet BiffaBin = NumberInBinary2sCompliment ' The RSet statement puts my current 2s compliment binary number at the right of the made string, ( and the rest of the characters become spaces, hence the characters I used to make the string was irrelevant!! )
Let NumberInBinary2sCompliment = Replace(BiffaBin, " ", "1", 1, -1, vbBinaryCompare) '
End If
End Function