1. [RESOLVED] Help with formula

I got this off the Net and it works... getting the size of 4 bytes in synchsafe format

Code:
```Function CalcSize(ss) As Long

Dim c As Long
Dim d As Long
Dim b As Long
b = 2 ^ 21
c = 2 ^ 14
d = 2 ^ 7

CalcSize = Asc(Mid(ss, 1, 1)) * b Or Asc(Mid(ss, 2, 1)) * c Or Asc(Mid(ss, 3, 1)) * d Or Asc(Mid(ss, 4, 1))
End Function```
Can someone help me work out the reverse please ... get the 4 byte values from the number?

Thanks

2. Re: Help with formula

i tested this and it returned the correct result
Code:
```Function revv(f)
Dim s As Long, t As Long, u As Long, v As Long
s = (f \ 2 ^ 21)
t = (f - s * 2 ^ 21) \ 2 ^ 14
u = (f - s * 2 ^ 21 - t * 2 ^ 14) \ 2 ^ 7
v = (f - s * 2 ^ 21 - t * 2 ^ 14 - u * 2 ^ 7)
revv = Chr(s) & Chr(t) & Chr(u) & Chr(v)
End Function```
it would probably be better to use more variables rather than as many recalculations

edit: this version increased the speed, though on a single iteration i doubt it has any relevance

Code:
```Function revv2(ByVal f)
Dim s As Long, t As Long, u As Long, v As Long
s = (f \ 2 ^ 21)
f = f - s * 2 ^ 21
t = f \ 2 ^ 14
f = f - t * 2 ^ 14
u = f \ 2 ^ 7
v = f - u * 2 ^ 7

revv2 = Chr(s) & Chr(t) & Chr(u) & Chr(v)
End Function```

3. Re: Help with formula

Thank you Pete. Works spot on and way above my maths level!
It'll be a huge help.
Cheers

4. Re: Help with formula

You're using variants quite a bit which are slower than a Typed variable. If you don't have a specific need for using variants, then you should avoid them.
For instance, parameter ss is a variant, and the functions revv and revv2 parameters are variants and the functions returns a variant.

You're using the variant form of the "string" functions, i.e. Mid and Chr rather than the string versions. The string versions will be faster than the variant versions.

Also, the Asc function will return the ASCII code for the first character of a string, so it turns out if you're using Mid\$ to pass a substring to Asc function it is quicker to drop the third parameter.

Essentially what the code is doing is just taking 7-bit values, and shifting them by multiples of 7-bits to pack four of them into 28-bits of a 32-bit long. I think it would probably be faster when doing the unpacking to just mask out the 7-bit field you want and then "shift" that down to "right" justify it.

So, doing what I described above, the two functions could look like this.
Code:
```Function CalcSize(ss As String) As Long
Const b As Long = 2 ^ 21
Const c As Long = 2 ^ 14
Const d As Long = 2 ^ 7

CalcSize = Asc(Mid\$(ss, 1)) * b Or Asc(Mid\$(ss, 2)) * c Or Asc(Mid\$(ss, 3)) * d Or Asc(Mid\$(ss, 4))
End Function

Function revv3(ByVal f) As String
Dim s As Long, t As Long, u As Long

s = (f And &HFE00000) \ 2 ^ 21
t = (f And &H1FC000) \ 2 ^ 14
u = (f And &H3F80) \ 2 ^ 7
revv3 = Chr\$(s) & Chr\$(t) & Chr\$(u) & Chr\$(f And &H7F)
End Function```

5. Re: [RESOLVED] Help with formula

Thanks for those refinements, Passel, I'll switch to using them. Some I knew and should have used but I'd focused on the showing the calculation which
you've explained very nicely !

6. Re: [RESOLVED] Help with formula

Thanks.
I was just looking back at Hex values of the masks, thinking how you should be able to see how the bit pattern is derivable from one to the next by seeing the value is a contiguous value of 7 bits and picks up where the previous one left off and it immediately jumped out at me this morning that the mask for variable s was wrong.
s = (f And &HF700000) ...

There are 7 bits set in the hex value F7, the four bits in the nibble F (a nibble is 1/2 a byte, i.e. 4-bits) and 3 bits in the nibble 7, but the three bits in 7 are the lower 3 bits, not the upper 3 bits of the nibble so the 7-bits set are not contiguous and span 8 bits instead of 7.

And if you look at the Hex mask for t, you see it is hex 1F, so 1 is the lowest bit in that nibble and that overlaps with 7 which would be the lower 3 bits of the nibble. So, instead of 7 and 1, which overlap, it should be E and 1 which don't overlap.

Therefore, the mask for s should have been &HFE00000, not &HF700000.
Code:
`  s = (f And &HFE00000) \ 2 ^ 21`
I'll correct post #4 in case someone comes across this thread and uses the code in post #4 without reading further down the thread.

7. Re: [RESOLVED] Help with formula

Nice one Passel, I was still implementing/testing. Quite possibly would never have known as that's the high byte and out of range for most values But good to get it right !
Thanks again

8. Re: [RESOLVED] Help with formula

Yeah. If I had written the four values in Hex in Notepad, or some other editor so I could keep them aligned, it would have been easier than doing it in my head.
Code:
```&H00000000
&H0000007F
&H00003F80
&H001FC000
&H3FE00000```
Perhaps if I had just written 32 zeros in groups of 4 and copied it four times and then set the 7-bit fields of ones manually in the four lines it might have been a little easier to align the bits than writing the hex directly.
Code:
```0000 0000 0000 0000 0000 0000 0000 0000 = 0
0000 0000 0000 0000 0000 0000 0111 1111 = 0000007F
0000 0000 0000 0000 0011 1111 1000 0000 = 00003F80
0000 0000 0001 1111 1100 0000 0000 0000 = 001FC000
0000 1111 1110 0000 0000 0000 0000 0000 = 0FE00000```
But, then again, I could just bring up a Visual Basic project in Visual Studio and go the immediate window and type in a string of 32 0's, then backover the last 7 and type seven 1's in and feed it to Convert.ToInt32 methods to convert binary string of digits to Int32 and then Convert.ToString to convert that Int32 into a Hex\$.

Then just hit the up arrow to repeat the line, but select the 7 zeros in front of the ones, Ctrl-X to cut them, and then paste them in after the ones to "shift" the seven ones up seven bits, and convert again. I think that is even quicker.
Code:
```? Convert.toString(Convert.toInt32("00000000000000000000000001111111",2),16)
"7f"
? Convert.toString(Convert.toInt32("00000000000000000011111110000000",2),16)
"3f80"
? Convert.toString(Convert.toInt32("00000000000111111100000000000000",2),16)
"1fc000"
? Convert.toString(Convert.toInt32("00001111111000000000000000000000",2),16)
"fe00000"```
Or could have used String.Format instead of Convert.ToString, but that is actually one character longer, e.g.
Code:
```? string.Format("{0:X}",Convert.ToInt32("0000000000000000000000001111111",2))
"7F"```
Interestingly, the results are slightly different as String.Format capitalizes the hex digits.

Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•

Featured