Get the value of bit in byte - C# - c#

I need to write the system to check either this user is valid or not by numbers issued for customer (NIC).
The data was given in forms of bytes with the total is 255 kilobytes, and I need to convert from bytes to bit. If 255 kb convert to bit, it will become 2,088,960.
Let say we take F9 as first byte, when convert to binary it will become 11111001.
NIC | Binary
1 = 1
2 = 1
3 = 1
4 = 1
5 = 1
6 = 0
7 = 0
8 = 1
0 = False
1 = True
For example,
NIC for this customer is number 3, so the value of bit is 1. So for another customer, let say his NIC is 6 then the value of bit is 0.
If the value of bit is 0, so this customer is valid. But if the value is 1, so this customer not valid.
So far what has done
var reader = com.ExecuteScalar() as byte[];
if (reader != null)
{
//From database to bytes array
list_bytes = reader;
//From bytes array to bit array
BitArray bits = new BitArray(list_bytes);
for (int a = 1; a <= NIC; a++)
{
//Debug purpose
if(a == NIC)
lblStatus.Text = Convert.ToBoolean(bits[a - 1]).ToString();
}
}
The problem is, let say I enter the NIC is 1 then it return = True. When I enter NIC is 2 then it return False but the answer should be True.
NIC 1 = True = 1
NIC 2 = False = 0
NIC 3 = False = 0
NIC 4 = True = 1
NIC 5 = True = 1
NIC 6 = True = 1
NIC 7 = True = 1
NIC 8 = True = 1
The binary is 10011111 and convert to byte is 0x9F, but the the data should be 0xF9.
I was Google for few hour ago and no one answer fit with my problems. Kindly let me know if this question not clear.

The binary is 10011111 and convert to byte is 0x9F, but the the data should be 0xF9.
The problem is that the first value you push on the array will be first value you are getting out of the array again (logic). But in your case, you don't want this, you want to start at the last value and work your way up to the first value, then it will work and ultimately return 0xF9.
for (int a = NIC; a >= 0; a--)
{
// Loop will run from NIC until it reaches 0. (can be 1 to, depending if your collection is zero-based)
}

This actually appears to be a rather simple problem covered up by too much code. One suggestion: forget about converting anything to bits. There is only pain that way.
As I understand it you have an array of bytes and each byte is a customer. The customer has a NIC and you simply want to check whether a particular bit is set in the customer's byte according to the NIC. The code looks something like this.
Byte customer_byte = list_bytes[customer_id];
Boolean isvalid = test_bit(customer_byte, customer_nic);
The NIC bits are numbered from 1 to 8, where 1 means 0x80 and 8 means 0x01. The test_bit function to do that could be written:
Boolean test_bit(Byte value, Int bitno) {
Byte mask = POW(2, 8 - bitno); // POW is the power function
return (value AND bitno) NEQ 0; // AND is the bitwise operator
}
I leave writing the actual code (and fixing my misunderstandings) as an exercise to the reader.

Related

How to convert bit to bit shift value

I have a difficulty selector set as an enum (None=0, Easy = 1<<0, Medium = 1<<1, Hard = 1<<2, Expert = 1<<3). Along with this, I have an array of point values I want to assign to these difficulties. So the array has indexes as so. [0, 100, 133, 166, 200].
The tricky bit, is this. I want to grab the index of the array, that is equivalent to the bit shift of the difficulty. So None = 0 (0000)-> Index = 0. Easy = 1 (0001)-> Index = 1. Medium = 2 (0010)-> Index = 2. Hard = 4 (0100) -> Index = 3. Expert = 8 (1000) -> Index = 4.
I tried doing the Square root originally, as I thought that it was powers of two, but quickly realized that it's actually not RAISED to two, it's just a base of two. So that would never work.
I also know I can get this value via a forloop, where I start at 8 (1000) for instance, and keep a counter as I shift right, and keep that going until it hits 0.
int difficulty = (int)LevelSetup.difficulty;
int difficultyIndex = 0;
while(difficulty != 0)
{
difficultyIndex++;
difficulty = difficulty >> 1;
}
currScorePerQuestion = ScorePerQuestion[difficultyIndex];
IE. Counter = 0; val = 8. | SHIFT | Counter = 1; val = 4; |SHIFT| Counter = 2; val = 2; |SHIFT| Counter = 3; val = 1; |SHIFT| Counter = 4; val = 0; |END| and we end with a value of 4.
The problem with this is that it seems really messy and overkill, especially if you wanted to go up to 64 bits and have lots of indicies. I just know that there is some kind of algorithm that I could use to convert these very simply. I am just struggling to come up with what that equation is exactly.
Any help is super appreciated, thanks!
After asking my friends. They came up with and gave me this solution.
As binary works by raising 2 to the nth power. We always have a base of 2, raised to the number that the bit is. So 2^4 is 8 which is the same as 1000 in binary.
Then, using the properties of Logarithms. You can use Log of base 2, which matches our base 2 powers, and take the log of it's value to get the exponential. ie Log2(2^3) = 3. And Log2(2^7) = 7.
luckily for us, binary matches this pattern completely, so a bit mask of (1000) is 8, which is equal to 2^3, so Log2(8) => 3.
To convert a bit into an index, ie (1000) is the 4th bit, so we want an index of 4.
Log base 2 of 8 -> Math.Log2(8) = 3. Then to get up to our 0 based index, we just add 1.
This leaves us with the following algorithm:
int difficulty = (int)LevelSetup.difficulty;
currScorePerQuestion = ScorePerQuestion[Math.Log2(difficulty)+1];

Need help writing a binary reader extension method for a specific value format: 6 bit then 7 bits structure

Alright so here goes.
I currently need to write an extension method for the System.IO.BinaryReader class that is capable of reading a specific format.
I have no idea what this format is called but I do know exactly how it works so i will describe it below.
Each byte that makes up the value is flagged to indicate how the reader will need to behave next.
The first byte has 2 flags, and any subsequent bytes for the value have only 1 flag.
First byte:
01000111
^^^^^^^^
|||____|_ 6 bit value
||_______ flag: next byte required
|________ flag: signed value
Next bytes:
00000011
^^^^^^^^
||_____|_ 7 bit value
|________ flag: next byte required
The first byte in the value has 2 flags, the first bit is if the value is positive or negative.
The second bit is if another byte needs to be read.
The 6 remaining bits is the value so far which will need to be kept for later.
If no more bytes need to be read then you just return the 6 bit value with the right sign as dictated by the first bit flag.
If another byte needs to be read then you read the first bit of that byte, and that will indicate if another byte needs to be read.
The remaining 7 bits are the value here.
That value will need to be joined with the 6 bit value from the first byte.
So in the case of the example above:
The first value was this: 01000111.
Which means it is positive, another byte needs to be read, and the value so far is 000111.
Another byte is read and it is this: 00000011
Therefore no new bytes need to be read and value here is this: 0000011
That is joined onto the front of the value so far like so: 0000011000111
That is therefore the final value: 0000011000111 or 199
0100011100000011 turns into this: 0000011000111
Here is another example:
011001111000110100000001
^^^^^^^^^^^^^^^^^^^^^^^^
| || ||______|_____ Third Byte (1 flag)
| ||______|_____________ Second Byte (1 flag)
|______|_____________________ First Byte (2 flags)
First Byte:
0 - Positive
1 - Next Needed
100111 - Value
Second Byte:
1 - Next Needed
0001101 - Value
Third Byte:
0 - Next Not Needed
0000001 - Value
Value:
00000010001101100111 = 9063
Hopefully my explanation was clear :)
Now i need to be able to write a clear, simple and, and most importantly fast extension method for System.IO.BinaryReader to read such a value from a stream.
My attempts so far are kind of bad and unnecessarily complicated involving boolean arrays and bitarrays.
Therefore I could really do with somebody helping me out with this in writing such a method, that would be really appreciated!
Thanks for reading.
Based on the description in the comments I came up with this, unusually reading in signed bytes since it makes the continue flag slightly easier to check: (not tested)
static int ReadVLQInt32(this BinaryReader r)
{
sbyte b0 = r.ReadSByte();
// the first byte has 6 bits of the raw value
int shift = 6;
int raw = b0 & 0x3F;
// first continue flag is the second bit from the top, shift it into the sign
sbyte cont = (sbyte)(b0 << 1);
while (cont < 0)
{
sbyte b = r.ReadSByte();
// these bytes have 7 bits of the raw value
raw |= (b & 0x7F) << shift;
shift += 7;
// continue flag is already in the sign
cont = b;
}
return b0 < 0 ? -raw : raw;
}
It can easily be extended to read a long too, just make sure to use b & 0x7FL otherwise that value is shifted as an int and bits would get dropped.
Version that checks for illegal values (an overlong sequence of 0xFF, 0xFF... for example, plus works with checked math of C# (there is an option in the C# compiler to use cheched math to check for overflows)
public static int ReadVlqInt32(this BinaryReader r)
{
byte b = r.ReadByte();
// the first byte has 6 bits of the raw value
uint raw = (uint)(b & 0x3F);
bool negative = (b & 0x80) != 0;
// first continue flag is the second bit from the top, shift it into the sign
bool cont = (b & 0x40) != 0;
if (cont)
{
int shift = 6;
while (true)
{
b = r.ReadByte();
cont = (b & 0x80) != 0;
b &= 0x7F;
if (shift == 27)
{
if (negative)
{
// minumum value abs(int.MinValue)
if (b > 0x10 || (b == 0x10 && raw != 0))
{
throw new Exception();
}
}
else
{
// maximum value int.MaxValue
if (b > 0xF)
{
throw new Exception();
}
}
}
// these bytes have 7 bits of the raw value
raw |= ((uint)b) << shift;
if (!cont)
{
break;
}
if (shift == 27)
{
throw new Exception();
}
shift += 7;
}
}
// We use unchecked here to handle int.MinValue
return negative ? unchecked(-(int)raw) : (int)raw;
}

What is the conventional way to convert a range of bits to an integer value in c# .net?

I've been programming for many years, but have never needed to use bitwise operations too much or really deal with data too much on a bit or even byte level, until now. So, please forgive my lack of knowledge.
I'm having to process streaming message frame data that I'm getting via socket communication. The message frames are a series of hex bytes encoded Big Endian which I read into a byte array called byteArray. Take the following 2 bytes for example:
0x03 0x20
The data I need is represented in the first 14 bits - meaning I need to convert the first 14 bits into an int value. (The last 2 bits represent 2 other bool values). I have coded the following to accomplish this:
if (BitConverter.IsLittleEndian)
{
Array.Reverse(byteArray);
}
BitArray bitArray = GetBitArrayFromRange(new BitArray(byteArray), 0, 14);
int dataValue = GetIntFromBitArray(bitArray)
The dataValue variable ends up with the correct result which is: 800
The two functions I'm calling are here:
private static BitArray GetBitArrayFromRange(BitArray bitArray, int startIndex, int length)
{
var newBitArray = new BitArray(length);
for (int i = startIndex; i < length; i++)
{
newBitArray[i] = bitArray.Get(i);
}
return newBitArray;
}
private static int GetIntFromBitArray(BitArray bitArray)
{
int[] array = new int[1];
bitArray.CopyTo(array, 0);
return array[0];
}
Since I have a lack of experience in this area, my question is: Does this code look correct/reasonable? Or, is there a more preferred/conventional way of accomplishing what I need?
Thanks!
"The dataValue variable ends up with the correct result which is: 800"
Shouldn't that correct result be actually 200?
1) 00000011 00100001 : is integer 0x0321 (so now skip beginning two bits 01...)
2) xx000000 11001000 : is extracted last 14 bits (missing 2 bits, so those xx count as zero)
3) 00000000 11001000 : is expected final result from 14-bits extraction = 200
At present it looks like you have an empty (zero filled) 16 bits into which you put the 14 bits. Somehow you putting in exact same position (left-hand side instead of right-hand side)
Original bits : 00000011 00100001
Slots 16 bit : XXXXXXXX XXXXXXXX
Instead of this : XX000000 11001000 //correct way
You have done : 00000011 001000XX //wrong way
Your right-hand side XX are zero so your result is 00000011 00100000 which would give 800, but that's wrong because it's not the true value of those specific 14 bits you extracted.
"Is there a more preferred/conventional way of accomplishing what I
need?"
I guess bit-shifting is the conventional way...
Solution (pseudo-code) :
var myShort = 0x0321; //Short means 2 bytes
var answer = (myShort >> 2); //bitshift to right-hand side by 2 places
By nudging everything 2 places/slots towards right, you can see how the two now-empty places at far-left becomes the XX (automatically zero until you change them), and by nudging you have also just removed the (right-side) 2 bits you wanted to ignore... Leaving you with correct 14-bit value.
PS:
Regarding your code... I've not had chance to test it all but the below logic seems more appropriate for your GetBitArrayFromRange function :
for (int i = 0; i < (length-1); i++)
{
newBitArray[i] = bitArray.Get(startIndex + i);
}

C# formula to determine index

I have a maths issue within my program. I think the problem is simple but I'm not sure what terms to use, hence my own searches returned nothing useful.
I receive some values in a method, the only thing I know (in terms of logic) is the numbers will be something which can be duplicated.
In other words, the numbers I could receive are predictable and would be one of the following
1
2
4
16
256
65536
etc
I need to know at what index they appear at. In othewords, 1 is always at index 0, 2 at index 1, 4 at index 3, 16 is at index 4 etc.
I know I could write a big switch statement but I was hoping a formula would be tidier. Do you know if one exists or any clues as the names of the math forumula's I'm using.
The numbers you listed are powers of two. The inverse function of raising a number to a power is the logarithm, so that's what you use to go backwards from (using your terminology here) a number to an index.
var num = 256;
var ind = Math.Log(num, 2);
Above, ind is the base-2 logarithm of num. This code will work for any base; just substitute that base for 2. If you are only going to be working with powers of 2 then you can use a special-case solution that is faster based on the bitwise representation of your input; see What's the quickest way to compute log2 of an integer in C#?
Try
Math.Log(num, base)
where base is 2
MSDN: http://msdn.microsoft.com/en-us/library/hd50b6h5.aspx
Logarithm will return to You power of base from you number.
But it's in case if your number really are power of 2,
otherwise you have to understand exactly what you have, what you need
It also look like numbers was powered to 2 twice, so that try this:
private static int getIndexOfSeries(UInt64 aNum)
{
if (aNum == 1)
return 0;
else if (aNum == 2)
return 1;
else
{
int lNum = (int)Math.Log(aNum, 2);
return 1+(int)Math.Log(lNum, 2);
}
}
Result for UInt64[] Arr = new UInt64[] { 1, 2, 4, 16, 256, 65536, 4294967296 } is:
Num[0] = 1
Num[1] = 2
Num[2] = 4
Num[3] = 16
Num[4] = 256
Num[5] = 65536
Num[6] = 4294967296 //65536*65536
where [i] - index
You should calculate the base 2 logarithm of the number
Hint: For the results:
0 2
1 4
2 16
3 256
4 65536
5 4294967296
etc.
The formula is, for a give integer x:
Math.Pow(2, Math.Pow(2, x));
that is
2 to the power (2 to the power (x) )
Once the formula is known, one could solve it for x (I won't go through that since you already got an answer).

Question On Validate Function On Byte Integer in C#

How can I validate a value is xx byte integer (singed or unsigned)
xx stand for 1, 2, 4, 8.
Supposed that I need validate 65(65 was a string value currently) is 1 byte integer or not?
How can I write a tiny function to validate it?
I don't know the exact meaning for byte integer.
bool Is1Byte(string val)
{
try
{
int num = int.Parse(val)
return (num >= -128) && (num <= 127);
}
catch(Exception)
{
return false;
}
}
It sounds like what you need is something that will test a number to see if it fits within a 1 byte integer. A 1 byte integer can contain a number between 0 and 255 (if unsigned) or -128 and 127 if signed. So you just need something that tests to see if the number falls within this range. byte is unsigned by default in C# so you just need:
return (x >= 0 && x <= 255);
Why these values? It's because a byte is eight bits of storage, which can store 2 to the 8 possible values. 2^8 = 256.

Categories

Resources