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.
Related
So I have a generator that creates a 26 hexadecimal character string that has a balance of ones and zeros when converted to binary. Actually 26.5.the first half of the 27th characters binary value is stored in a buf. and the last half is used to make the first 106 bits nice and even. Or should at least. How would I use the binary remnants in the buf to generate the the 27th char and to make the last 22 bits into a hash/checksum for the first 106? below is my generator.
Dim rnd As New Random()
Dim bin As New StringBuilder()
Dim buf As Integer = 0, bufLen As Integer = 0, left As Integer = 53
For i As Integer = 106 To 0 Step -1
buf <<= 1
If rnd.[Next](i) < left Then
buf += 1
left -= 1
End If
If System.Threading.Interlocked.Increment(bufLen) = 4 Then
bin.Append("0123456789abcdef"(buf))
bufLen = 0
buf = 0
End If
Next
Dim b As String = bin.ToString()
TextBox1.Text = (b)
How would I add on to this completing the process?
You've got 106 to 0 step -1, which means 107 iterations creating 26 hex digits with three further bits in buf (though the last one's guaranteed to be 0)... you might as well make it 108 and have it add an extra hex digit to bin - it doesn't matter that it's also 0, then you can apply any >=22 bit hash/checksum algo you like to the data in bin and append the hash/checksum value - you obviously know how to slice the least significant 4 bits off the left, generate the hex digit, and rotate - the last time you can AND with 3 and OR or XOR the value over the final hex digit you generated - setting the two trailing 0s added above. Googling "VB checksum" turns up lots of example code. If you get stuck, post your code and specific problem.
Separately, I don't know VB so maybe there's some weird reason, but I can't imagine why you're using what appears to be a threadsafe increment for a local variable which I'd assume in on the executing thread's stack and inaccessible to other threads?
I am programming a fixed-point speech enhancement algorithm on a 16-bit processor. At some point I need to do 32-bit fractional multiplication. I have read other posts about doing 32-bit multiplication byte by byte and I see why this works for Q0.31 formats. But I use different Q formats with varying number of fractional bits.
So I have found out that for fractional bits less than 16, this works:
(low*low >> N) + low*high + high*low + (high*high << N)
where N is the number of fractional bits. I have read that the low*low result should be unsigned as well as the low bytes themselves. In general this gives exactly the result I want in any Q format with less than 16 fractional bits.
Now it gets tricky when the fractional bits are more than 16. I have tried out several numbers of shifts, different shifts for low*low and high*high I have tried to put it on paper, but I can't figure it out.
I know it may be very simple but the whole idea eludes me and I would be grateful for some comments or guidelines!
It's the same formula. For N > 16, the shifts just mean you throw out a whole 16-bit word which would have over- or underflowed. low*low >> N means just shift N-16 bit in the high word of the 32-bit result of the multiply and add to the low word of the result. high * high << N means just use the low word of the multiply result shifted left N-16 and add to the high word of the result.
There are a few ideas at play.
First, multiplication of 2 shorter integers to produce a longer product. Consider unsigned multiplication of 2 32-bit integers via multiplications of their 16-bit "halves", each of which produces a 32-bit product and the total product is 64-bit:
a * b = (a_hi * 216 + a_lo) * (b_hi * 216 + b_lo) =
a_hi * b_hi * 232 + (a_hi * b_lo + a_lo * b_hi) * 216 + a_lo * b_lo.
Now, if you need a signed multiplication, you can construct it from unsigned multiplication (e.g. from the above).
Supposing a < 0 and b >= 0, a *signed b must be equal
264 - ((-a) *unsigned b), where
-a = 232 - a (because this is 2's complement)
IOW,
a *signed b =
264 - ((232 - a) *unsigned b) =
264 + (a *unsigned b) - (b * 232), where 264 can be discarded since we're using 64 bits only.
In exactly the same way you can calculate a *signed b for a >= 0 and b < 0 and must get a symmetric result:
(a *unsigned b) - (a * 232)
You can similarly show that for a < 0 and b < 0 the signed multiplication can be built on top of the unsigned multiplication this way:
(a *unsigned b) - ((a + b) * 232)
So, you multiply a and b as unsigned first, then if a < 0, you subtract b from the top 32 bits of the product and if b < 0, you subtract a from the top 32 bits of the product, done.
Now that we can multiply 32-bit signed integers and get 64-bit signed products, we can finally turn to the fractional stuff.
Suppose now that out of those 32 bits in a and b N bits are used for the fractional part. That means that if you look at a and b as at plain integers, they are going to be 2N times greater than what they really represent, e.g. 1.0 is going to look like 2N (or 1 << N).
So, if you multiply two such integers the product is going to be 2N*2N = 22*N times greater than what it should represent, e.g. 1.0 * 1.0 is going to look like 22*N (or 1 << (2*N)). IOW, plain integer multiplication is going to double the number of fractional bits. If you want the product to
have the same number of fractional bits as in the multiplicands, what do you do? You divide the product by 2N (or shift it arithmetically N positions right). Simple.
A few words of caution, just in case...
In C (and C++) you cannot legally shift a variable left or right by the same or greater number of bits contained in the variable. The code will compile, but not work as you may expect it to. So, if you want to shift a 32-bit variable, you can shift it by 0 through 31 positions left or right (31 is the max, not 32).
If you shift signed integers left, you cannot overflow the result legally. All signed overflows result in undefined behavior. So, you may want to stick to unsigned.
Right shifts of negative signed integers are implementation-specific. They can either do an arithmetic shift or a logical shift. Which one, it depends on the compiler. So, if you need one of the two you need to either ensure that your compiler just supports it directly
or implement it in some other ways.
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?
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
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