[RESOLVED] Need math help, extracting bytes from Long
I need to pack four individual Byte variables into a single Long variable, and then be able to split that Long back into its four constituent Bytes. (For use in a Listbox ItemData property.)
I haven't a clue where to begin. Anyone know? Speed/efficiency isn't mission critical, but elegance is always appreciated.
Re: Need math help, extracting bytes from Long
The 4th byte is the tricky part unless it's value is never > 127.
Creating packed Long
1st byte: lValue = lValue Or Byte
2nd byte: lValue = lValue Or (Byte * &H100&)
3rd byte: lValue = lValue Or (Byte * &H10000)
4th byte
-- < 128? lValue = lValue Or (Byte * &H1000000)
-- > 127? lValue = lValue Or ((Byte XOR &H80) * &H1000000) Or &H80000000
Extraction:
1st byte: Byte = lValue And &HFF&
2nd byte: Byte = (lValue And &HFF00&) \ &H100&
3rd byte: Byte = (lValue And &HFF0000) \ &H10000
4th byte:
-- lValue non-negative? Byte = (lValue And &HFF000000) \ &H1000000
-- lValue is negative? Byte = (lValue And &H7F000000) \ &H1000000 Or &H80
Re: Need math help, extracting bytes from Long
more cat skinning
Code:
Option Explicit
Private Type tByte4
b1 As Byte
b2 As Byte
b3 As Byte
b4 As Byte
End Type
Private Type tLong
n As Long
End Type
Private Function Pack(ByVal byts As tByte4) As Long
Dim lng As tLong
LSet lng = byts
Pack = lng.n
End Function
Private Function UnPack(ByVal number As Long) As tByte4
Dim lng As tLong
lng.n = number
LSet UnPack = lng
End Function
Private Function Pack2(ByVal b1 As Byte, ByVal b2 As Byte, ByVal b3 As Byte, ByVal b4 As Byte) As Long
Dim byts As tByte4, lng As tLong
byts.b1 = b1
byts.b2 = b2
byts.b3 = b3
byts.b4 = b4
LSet lng = byts
Pack = lng.n
End Function
Private Function Pack3(ByVal b1 As Byte, ByVal b2 As Byte, ByVal b3 As Byte, ByVal b4 As Byte) As Long
Pack = b1 Or b2 * &H100& Or b3 * &H10000
Pack = Pack Or (b4 And &H7F&) * &H1000000 Or (b4 And &H80&) * &HFF000000
End Function
Private Function UnPack2(ByVal number As Long) As tByte4
With UnPack
.b1 = (number And &HFF&)
.b2 = (number And &HFF00&) \ &H100&
.b3 = (number And &HFF0000) \ &H10000
.b4 = (number And &H7F000000) \ &H1000000 Or (number And &H80000000) \ &HFF000000
End With
End Function
Re: Need math help, extracting bytes from Long
Cool, thanks. I've been googling around since I posted the OP, and I think I found a faster, more elegant way that uses just pure native VB. Plus you get the full range of values in every byte with no overflow issues. Check it out:
vb Code:
Private Type LongType
Value As Long
End Type
Private Type TwoIntsType
Int1 As Integer
Int2 As Integer
End Type
Private Type FourBytesType
Byte1 As Byte
Byte2 As Byte
Byte3 As Byte
Byte4 As Byte
End Type
Public Sub Sample(plngTest As Long) As Long
Dim typLong As LongType
Dim typInts As TwoIntsType
Dim typBytes As FourBytesType
Debug.Print "Long: " & plngTest
' Convert Long to Integers
typLong.Value = plngTest
LSet typInts = typLong
With typInts
Debug.Print "Integers: " & .Int1, .Int2
End With
' Convert Integers to Bytes
LSet typBytes = typInts
With typBytes
Debug.Print "Bytes: " & .Byte1, .Byte2, .Byte3, .Byte4
End With
' Convert Bytes to Long
LSet typLong = typBytes
Debug.Print "Long: " & plngTest
End Function
Sample:
Code:
sample 1234567890
Long: 1234567890
Integers: 722 18838
Bytes: 210 2 150 73
Long: 1234567890
Even the help file documents this. Turns out that LSet() is a native VB command that is functionally equivalent to CopyMemory for UDTs. All you need to do is make sure they're the same size.
That's way cool.
EDIT: Yeah, I've been playing around with this for an hour. I should probably preview before posting, eh? This post was in response to LaVolpe, not Milk. In any case, thanks much to both of you.
Re: [RESOLVED] Need math help, extracting bytes from Long
Whichever floats your boat ;)
I'll probably never change my methods simply because bit shifting/masking is very comfortable for me, requires no structures, and is very fast indeed.