-
Feb 7th, 2018, 12:12 AM
#1
Thread Starter
Frenzied Member
[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
-
Feb 7th, 2018, 03:25 AM
#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
Last edited by westconn1; Feb 7th, 2018 at 04:13 AM.
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case.
Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
-
Feb 7th, 2018, 04:48 PM
#3
Thread Starter
Frenzied Member
Re: Help with formula
Thank you Pete. Works spot on and way above my maths level!
It'll be a huge help.
Cheers
-
Feb 8th, 2018, 12:30 AM
#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
Last edited by passel; Feb 8th, 2018 at 06:16 AM.
-
Feb 8th, 2018, 01:57 AM
#5
Thread Starter
Frenzied Member
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 !
-
Feb 8th, 2018, 06:14 AM
#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.
-
Feb 8th, 2018, 11:11 PM
#7
Thread Starter
Frenzied Member
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
-
Feb 9th, 2018, 03:10 AM
#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.
Last edited by passel; Feb 9th, 2018 at 03:31 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|