I'm trying to figure out how to calculate the lower 7 bits and 7-13 bits of two hex numbers.
Here is some example c code, just need this in vb.net:
serialBytes[2] = 0x64 & 0x7F; // Second byte holds the lower 7 bits of target.
serialBytes[3] = (0x64 >> 7) & 0x7F; // Third data byte holds the bits 7-13 of target
The 0x7F is a constant so the only number that changes based off input is the 0x64.
Can someone help me out?
The code translates into this VB code:
serialBytes(2) = &h64 And &h7F
serialBytes(3) = (&h64 >> 7) And &h7F
If the hex value 64 is actually a variable input, just replace &h64 with the input variable. If the input is an integer, you have to cast the results to byte, though:
serialBytes(2) = CType(value And &H7F, Byte)
serialBytes(3) = CType((value >> 7) And &H7F, Byte)
VB.NET has no bit shift operators, but does have the bitwise operator And:
set bits1to7 = value And &H007F
set bits8to14 = value And &H3F80
Edit:
VB.NET does have bit shift operators (my bad) since .NET Framework 1.1, so the more systematic approach is indeed also possible:
set bits1to7 = value And &H7F
set bits8to14 = (value >> 7) And &H7F
Related
I'm reading an ancient data file that is basically a flattened object store with type flags - for instance, 1=Int16, 2=Int32. To read the Int32's, for instance, I read 4 bytes out of the stream and then did this:
If B.Length >= 2 + Offset Then
Ans = Convert.ToUInt16(B(1 + Offset) * 256 + B(0 + Offset))
End If
Now I am at a bit of a loss how to do the 3=Double. These are 8-byte values, IEEE I assume. There is a Convert.ToDouble(byte), but that's not the same thing, that just returns a Double containing a value from 0 to 255. Likewise, Convert.ToDouble(Int64) basically just casts the value to Double.
So what's the trick here? I found threads for doing it in VB6 and C, but not VB.net.
I am trying to combine three Byte values to one Long value, like System.Drawing.Color.ToArgb() does.
I've looked up reference source code to find it and converted it to VB .NET:
Return CLng((CInt(red) << 16 Or CInt(green) << 8 Or blue Or CInt(alpha) << 24) And -1)
It works fine of course, but I don't really understand why alpha shifted by 24 is last, not first (so it would be in nice order 24, 16, 8). I don't really understand bitwise operations a lot. Also, this code snippet works for 4 bytes, which is redundant for me, I need just three bytes and I wonder if Long is still required when bytes are only three, wouldn't Integer do just fine in this case?
So, my question is, how do I rewrite this code to work with just 3 parameters? Do I need to use Long? And, I know this is silly, but is it possible to make byte shifting in order 16,8,0 instead of 16,8,0,24? It's really just aesthetics, but I am awful perfectionist.
Thanks in advance!
Aaron
Here are some different ways. The order of the OR's does not matter. I added some debugs so you can see the results as you go.
Private Sub Button1_Click(sender As System.Object, _
e As System.EventArgs) Handles Button1.Click
Dim bar As Integer '32 bits
'three byte values
Dim x As Byte = 66
Dim y As Byte = 65
Dim z As Byte = 82
'desired byte order
'0xyz
'one byte at a time
bar = 0
bar = bar Or (CInt(x) << 16)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
bar = bar Or (CInt(y) << 8)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
bar = bar Or (CInt(z) << 0) 'bar Or CInt(z)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
'or as single statement
bar = 0 Or (CInt(x) << 16) Or (CInt(y) << 8) Or CInt(z)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
'in any order
bar = 0 Or CInt(z) Or (CInt(y) << 8) Or (CInt(x) << 16)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
'check results
Dim foo() As Byte = BitConverter.GetBytes(bar) 'get the individual bytes
Array.Reverse(foo) 'reverse
Debug.WriteLine(System.Text.ASCIIEncoding.ASCII.GetChars(foo, 1, 3))
End Sub
It doesn't matter, a OR b is the same value as b OR a. The OR operator is commutative, just like the + and * operators.
An Integer can store the value just fine, it has 32 bits. Using UInteger instead can be useful to deal with alpha values larger than 127 turning the value negative. Which will give you a bit of a headache when you try to read the alpha value back. Sign extension produces a large value, fixed by AND-ing with 255. Long was common in VB6 code since its Integer type had only 16 bits, not an issue in vb.net.
I'm not familiar with VB.NET, but in general there is no right or wrong order of the shift count. It can be 24, 16, 8, 0 or 16, 24, 0, 8 or any other order.
And regrading the variable type: There are 8-bit, 16-bit and 32-bit variables. That means you must define a 32-bit type (long) in order to have room for your three bytes.
For easy access, leave the 8 MSB bits as 0 so you can use it as a 24-bit value (0x00YYYYYY).
I have a byte array with 512 Elements and need to get and set a single bit of a byte in this array.
The operation must not change any other bits, only the specified one.
So if I have a byte like &B00110011 and would like to change the third bit to 1 it should be &B00110111.
Like this:
Dim myarray(511) as byte
myarray(3).2 = 1 ---> This would change the third bit (start counting at 0) of the third byte to 1
I know it should be easily possible using bit-masking but I don't have the time to try for days to get it working.
Thanks for help!!!
Jan
A simple way to do this is using shifts. If you want to set the Nth bit of a number to 1:
mask = 1 << n ' if n is 3, mask results in 00001000
bytevalue = bytevalue or mask
To set a bit as 0:
mask = 255 - (1 << n) ' if n is 3, mask results in 11110111
bytevalue = bytevalue and mask
In both examples, bytevalue is the byte in which you want to alter and mask is also a byte.
EDIT: To retrieve the state of a bit easily is a lot like setting a bit, Where IsSet is a boolean:
mask = 1 << n ' just as above
IsSet = (bytevalue and mask) <> 0
Why don't you use the BitArray class?
Can anyone offer any advice on how to get the mantissa and exponent from a double in VB.net? I know I can do a string parse and some conversion to ints but I wondered if anyone had a mathematical equivalent formula that would allow me to do this?
Many thanks
Do you want to get the "native" mantissa and exponent within the IEEE-754 value? That's actually fairly easy: use BitConverter.DoubleToInt64Bits to get the value as an integer (which is easier to perform bit operations on) and then see my article on .NET binary floating point types for which bits are where.
I have some C# code which extracts the various parts in order to convert it to a precise decimal representation - you could convert the relevant bits of that into VB reasonably easily.
You should try this:
Public Function DeclString(ByVal dDegrees As Double) As String
Dim Flag As String
Dim ddecimal As Double
Dim iDegrees As Integer
If dDegrees < 0 Then Flag = "S" Else Flag = "N"
iDegrees = Int(Abs(dDegrees))
ddecimal = (Abs(dDegrees) - iDegrees) * 60 ' + 0.5
If ddecimal > 59.5 Then iDegrees = iDegrees + 1: ddecimal = 0
DeclString = Format$(iDegrees, "00") + Flag + Format$(ddecimal, "00")
End Function
Please excuse my lack of knowledge here but could someone let me know how i can get the first 16 bits of a 32 bit hex number.
That depends on what you mean by "first". Given a number, such as 0xdeadbeef, would you consider 0xdead or 0xbeef to be "first"?
If the former, divide the number by 65536 (as an integer). If the latter, compute the modulus to 65536.
This is of course also doable with binary operators such as shift/and, I'm just not sure sure how to express that in your desired language. I'm sure there will be other answers with more precise details.
Assuming by first, you mean least value?
if My32BitNumber is an int
dim f16 as integer = &hFFFF and My32BitNumber
If you're actually looking at a 32 bit number e.g. Gee, what are the first 16 bits of DEADBEEF
that would be the last four hex digits BEEF
& it with 0xffff.
int input = 0xabcd;
int first2Bytes = input & 0xffff;
Dim i As Integer = &HDEADBEEF
Dim s16 As UShort
s16 = i And &HFFFF 'BEEF
'or
s16 = (i >> 16) And &HFFFF 'DEAD
This will get you the 32 bit number as a four byte array:
Dim bytes As Byte() = BitConverter.GetBytes(number)
To get the first two bytes as a signed 16 bit number:
Dim first As Int16 = BitConverter.ToInt16(bytes, 0)
To get the first two bytes as an unsigned 16 bit number:
Dim first As UInt16 = BitConverter.ToUInt16(bytes, 0)
This is of course a bit slower than using bit shifts or division, but it handles the sign bit (the most significant bit) correctly, which you may have problems with using bit shift or division.
You can also get the first two bytes as a 16 bit unsigned number and assign it to an Integer:
Dim first As Integer = BitConverter.ToUInt16(bytes, 0)
(Getting a signed 16 bit number and assign to an Integer means that the sign bit would also be copied to the top 16 bits of the Integer, which is probably not desired.)
If you want the last two bytes (least significant) instead of the first two (most significant), just change the index in the ToUInt16/ToInt16 call from 0 to 2.