I want to perform a bitwise-AND operation in VB.NET, taking a Short (16-bit) variable and ANDing it with '0000000011111111' (thereby retaining only the least-significant byte / 8 least-significant bits).
How can I do it?
0000000011111111 represented as a VB hex literal is &HFF (or &H00FF if you want to be explicit), and the ordinary AND operator is actually a bitwise operator. So to mask off the top byte of a Short you'd write:
shortVal = shortVal AND &HFF
For more creative ways of getting a binary constant into VB, see: VB.NET Assigning a binary constant
Use the And operator, and write the literal in hexadecimal (easy conversion from binary):
theShort = theShort And &h00ff
If what you are actually trying to do is to divide the short into bytes, there is a built in method for that:
Dim bytes As Byte() = BitConverter.GetBytes(theShort)
Now you have an array with two bytes.
result = YourVar AND cshort('0000000011111111')
Related
I need to convert a ByteString to a Float32 (Exactly a 32-bit big-endian IEEE 754 floating point number). The ByteString is a part of an open sound control stream, received via UDP client.
I've spent a lot of time researching, so I'd like of someone handy with Smalltalk could give me a solution.
Thanks, in advance.
Since you seem to be receiving binary data, and not a decimal number in formatted ASCII, I would not recommend to call it ByteString, but rather ByteArray, Strings are an abstraction for containing characters, not bits.
In the case of VisualWorks, there is a class called UninterpretedBytes specialized in storing raw data (bits or rather bytes) for later interpretation.
This class has all the message you need to interpret the bytes, like for example #floatAt:bigEndian:
| yourBinaryStream buffer |
yourBinaryStream := ... insert some code to create your stream here...
buffer:= UninterpretedBytes from: (yourBinaryStream next: 4).
nextFloat := buffer floatAt: 1 bigEndian: true
In Pharo Smalltalk you can do:
(Float readFrom: '4.2') asIEEE32BitWord
readFrom: just reads a float from a string, and then you convert it to IEEE 754...
In VisualWorks you need to use the superclass method readFrom: as implemented in class Number.
First create a readstream on the string, for example:
Number readFrom: '192843.887' readStream
I do:
Dim BytArr() as Byte = BitConverter.GetBytes(1234)
Since, by default, they are 32 bits, it returns 4 byte elements.
I want to be able to control it to return only like two bytes. Maybe only three bytes. Are there any built-in functions to control it?
I don't want to rely on using shifting >> 8 >> 16 >> 24 >> 32, etc..
I also don't want to rely on type casting the data in GetBytes() to a specific datatype.
It is not that GetBytes defaults to 32 bits, it is that GetBytes returns an array of the size required to hold the data type. If you pass a Long then you will get a 8 elements in your array.
The best way to control this is indeed casting the data you pass in. Otherwise you could truncate some of the number.
That being said, you could do something like this:
Dim BytArr() as Byte = Array.Resize(BitConverter.GetBytes(1234), 2)
But if the value you passed in exceeded what could be stored in 2 bytes (in this case) then you will have some very broken code.
I have a system which deals with keys that have been turned into unsigned long integers (by packing short sequences into byte strings). I want to try storing these in Redis, and I want to do it in the best way possible. My concern is mainly memory efficiency.
From playing with the online REPL I notice that the two following are identical
zadd myset 1.0 "123"
zadd myset 1.0 123
This means that even if I know I want to store an integer, it has to be set as a string. I notice from the documentation that keys are just stored as char*s and that commands like SETBIT indicate that Redis is not averse to treating strings as bytestrings in the client. This hints at a slightly more efficient way of storing unsigned longs than as their string representation.
What is the best way to store unsigned longs in sorted sets?
Thanks to Andre for his answer. Here are my findings.
Storing ints directly
Redis keys must be strings. If you want to pass an integer, it has to be some kind of string. For small, well-defined sets of values, Redis will parse the string into an integer, if it is one. My guess is that it will use this int to tailor its hash function (or even statically dimension a hash table based on the value). This works for small values (examples being the default values of 64 entries of a value of up to 512). I will test for larger values during my investigation.
http://redis.io/topics/memory-optimization
Storing as strings
The alternative is squashing the integer so it looks like a string.
It looks like it is possible to use any byte string as a key.
For my application's case it actually didn't make that much difference storing the strings or the integers. I imagine that the structure in Redis undergoes some kind of alignment anyway, so there may be some pre-wasted bytes anyway. The value is hashed in any case.
Using Python for my testing, so I was able to create the values using the struct.pack. long longs weigh in at 8 bytes, which is quite large. Given the distribution of integer values, I discovered that it could actually be advantageous to store the strings, especially when coded in hex.
As redis strings are "Pascal-style":
struct sdshdr {
long len;
long free;
char buf[];
};
and given that we can store anything in there, I did a bit of extra Python to code the type into the shortest possible type:
def do_pack(prefix, number):
"""
Pack the number into the best possible string. With a prefix char.
"""
# char
if number < (1 << 8*1):
return pack("!cB", prefix, number)
# ushort
elif number < (1 << 8*2):
return pack("!cH", prefix, number)
# uint
elif number < (1 << 8*4):
return pack("!cI", prefix, number)
# ulonglong
elif number < (1 << 8*8):
return pack("!cQ", prefix, number)
This appears to make an insignificant saving (or none at all). Probably due to struct padding in Redis. This also drives Python CPU through the roof, making it somewhat unattractive.
The data I was working with was 200000 zsets of consecutive integer => (weight, random integer) × 100, plus some inverted index (based on random data). dbsize yields 1,200,001 keys.
Final memory use of server: 1.28 GB RAM, 1.32 Virtual. Various tweaks made a difference of no more than 10 megabytes either way.
So my conclusion:
Don't bother encoding into fixed-size data types. Just store the integer as a string, in hex if you want. It won't make all that much difference.
References:
http://docs.python.org/library/struct.html
http://redis.io/topics/internals-sds
I'm not sure of this answer, it's more of a suggestion than anything else. I'd have to give it a try and see if it works.
As far as I can tell, Redis only supports UTF-8 strings.
I would suggest grabbing a bit representation of your long integer and pad it accordingly to fill up the nearest byte. Encode each set of 8 bytes to a UTF-8 string (ending up with 8x*utf8_char* string) and store that in Redis. The fact that they're unsigned means that you don't care about that first bit but if you did, you could add a flag to the string.
Upon retrieving the data, you have to remember to pad each character to 8 bytes again as UTF-8 will use less bytes for the representation if the character can be stored with less bytes.
End result is that you store a maximum of 8 x 8 byte characters instead of (possibly) a maximum of 64 x 8 byte characters.
If varShort in VB.NET is a Short and varBit is a value from 0 to 15, how can I set the bit in varShort identified by varBit without disturbing any of the other bits in varShort?
My problem, of course, is with the most significant bit, bit 15. Since varBit is determined at runtime, the solution must work with any bit number.
You can use the bitshift operators, << and >>, to turn on the bit you want (and put this value in varValue), and then bitwise Or varShort and varValue
There is information in this question about the bitshift operators in VB.NET
Setting the sixteenth bit of a Short will cause an overflow exception because Short is a signed type. Do you have any reason not to use the unsigned counterpart UShort?
Edit
If you really want to stick with Short, this function will set the sixteenth bit:
Function setNthBit(ByVal number As Short, ByVal bit As Short) As Short
Dim mask As UShort
mask = 2 ^ bit
If mask > Short.MaxValue Then
Return (Short.MinValue + number) Or mask
Else
Return number Or mask
End If
End Function
select convert(varbinary(8), 1) in MS SQL Server produces output : 0x00000001
On assigning the above query to dataset in Delphi, and accessing field value, we get byte array as [1, 0, 0, 0] . So Bytes[0] contains 1.
When I use IntToHex() on this bytes array it would result me value as "10000000" .
Why is IntToHex considering it in reverse order?
Thanks & Regards,
Pavan.
I think you forgot to include a reference to the code where you're somehow calling IntToHex on a TBytes array. It's from the answer to your previous question, how to convert byte array to its hex representation in Delphi.
In my answer, I forgot to account for how a pointer to an array of bytes would have the bytes in big-endian order while IntToHex (and everything else on x86) expects them in little-endian order. The solution is to switch them around. I used this function:
function Swap32(value: Integer): Integer;
asm
bswap eax
end;
In the meantime, I fixed my answer to account for that.
This seems to be a little/big endian problem. Just reverse the byte array or the return value from IntToHex. Another way would be to do it yourself:
myInt = Bytes[0];
Inc(myInt, (Bytes[1] shl 8));
Inc(myInt, (Bytes[2] shl 16));
Inc(myInt, (Bytes[3] shl 24));
Also be careful with the sign. Is the SQL value signed or unsigned - the Delphi datatype should match this (int/longint is signed, Longword/Cardinal is unsigned - see here or in the Delphi Help).
Because the x86 CPU uses little-endian numbers, a numbering system which orders its bytes in reverse order. You'll need to swap the byte order to get the right value.