This code:
BitArray bits = new BitArray(new byte[] { 7 });
foreach (bool bit in bits)
{
Console.WriteLine(bit ? 1 : 0);
}
Gives me the following output:
11100000
Shouldn't it be the other way around? Like this:
00000111
I am aware that there is little and big endian, although those terms only refer to the position of bytes. As far as I know, they don't affect bits.
The documentation for BitArray states:
The first byte in the array represents bits 0 through 7, the second
byte represents bits 8 through 15, and so on. The Least Significant
Bit of each byte represents the lowest index value: " bytes [0] & 1"
represents bit 0, " bytes [0] & 2" represents bit 1, " bytes [0] & 4"
represents bit 2, and so on.
When indexing bits, the convention is to start at the least significant end, which is the right side when written in binary notation. However, when enumerating the array, you start at index 0, so they are printed out left-to-right instead of right-to-left. That's why it looks backwards.
For example, the word 01011010 00101101 (90 45) would be indexed as:
0 1 0 1 1 0 1 0 - 0 0 1 0 1 1 0 1
----------------------- -----------------------
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
And you would pass it to the constructor as new byte[] { 45, 90 } since you pass it least-significant first. When printed out, it would display in index order as: 1011010001011010, which is the reverse of the original binary notation.
The documentation is not explicit about it, but I guess the iterator iterates from the LSB to the MSB. Sound reasonable to me (personally!), unless you are printing out the bits. I had a look at BitArray.GetEnumerator Method.
No it's a bit array, not a numeric value represented as bits.
It's just like any regular array with some methods added for bit operations. Just like if you had an array of int. You wouldn't expect it to be in the reverse order, it just takes it position by position.
Eg:
Numbers (in a byte) converted to a BitArray would come out like:
2 = 01000000
5 = 10100000
8 = 00010000
etc.
It just stores the position of the value but not relative as you would except from a binary numeric value.
Here is a link describing the constructor you are using:
http://msdn.microsoft.com/en-us/library/b3d1dwck.aspx
The key point is:
The number in the first values array element represents bits 0 through
31, the second number in the array represents bits 32 through 63, and
so on. The Least Significant Bit of each integer represents the lowest
index value: " values [0] & 1" represents bit 0, " values [0] & 2"
represents bit 1, " values [0] & 4" represents bit 2, and so on.
Related
We know that an int value has a maximum value of 2^31 - 1 and a minimum value of -2^31. If we were to set int to the maximum value:
int x = int.MaxValue;
And we take that x and add one to it in a unchecked field
unchecked
{
x++;
}
Then we get x = the minimum value of int. My question is why does this happen and how does it happen in terms of binary.
In C#, the built-in integers are represented by a sequence of bit values of a predefined length. For the basic int datatype that length is 32 bits. Since 32 bits can only represent 4,294,967,296 different possible values (since that is 2^32),
Since int can hold both positive and negative numbers, the sign of the number must be encoded somehow. This is done with first bit. If the first bit is 1, then the number is negative.
Here are the int values laid out on a number-line in hexadecimal and decimal:
Hexadecimal Decimal
----------- -----------
0x80000000 -2147483648
0x80000001 -2147483647
0x80000002 -2147483646
... ...
0xFFFFFFFE -2
0xFFFFFFFF -1
0x00000000 0
0x00000001 1
0x00000002 2
... ...
0x7FFFFFFE 2147483646
0x7FFFFFFF 2147483647
As you can see from this chart, the bits that represent the smallest possible value are what you would get by adding one to the largest possible value, while ignoring the interpretation of the sign bit. When a signed number is added in this way, it is called "integer overflow". Whether or not an integer overflow is allowed or treated as an error is configurable with the checked and unchecked statements in C#.
This representation is called 2's complement
You can check this link if you want to go deeper.
Int has a maximum value of 2^31 - 1 because , int is an alias for Int32 that stores 4 bytes in memory to represent the value.
Now lets come to the concept of int.Max + 1. Here you need to know about the Signed number representations that is used to store the negative values. In Binary number representation, there's nothing like negative numbers but they are represented by the one's complement and two's complement bits.
Lets say, my int1 has a storage memory of 1 byte, ie. 8 bits. So Max value you can store into int1 is 2^8 -1 = 255 . Now let's add 1 into this value-
11111111
+ 00000000
----------
100000000
your output is 100000000 = (512) in decimal, that is beyond the storage capacity of int1 and that represents the negative value of -256 in decimal (as first bit shows the negative value).
This is the reason adding 1 to int.Max become, int.Minimum. ie.
`int.Maximum + 1 = int.Minimum`
Okay, I'm going to assume for sake of convenience that there's a 4 bit integer type in C#. The most significant bit is used to store the sign, the remaining three are used to store the magnitude.
The max number that can be stored in such a representation is +7 (positive 7 in the base 10). In binary, this is:
0111
Now let's add positive one:
0111
+0001
_____
1000
Whoops, that carried over from the magnitudes and flipped the sign bit! The sum you see above is actually the number -8, the smallest possible number that can be stored in this representation. If you're not familiar with two's complement, which is how signed numbers are commonly represented in binary, you might think that number is negative zero (which would be the case in a sign and magnitude representation). You can read up on two's complement to understand this better.
I have a device and I have some values that user sets in GUI, that will be like 630 330 etc. I need these values passed to I2C bytes. 583will be 02 47 in hex bits. that will be in 2 byte variables and I need to call Set(byte lower ,byte upper) so to convert an int or double value to 2 bytes is the requirement.
I tried :
ushort R1x = (ushort)Rx;
byte upper = (byte)(R1x >> 8);
byte lower = (byte)(R1x & 0xff);
What I needed is lower = 47 and upper = 02.
Which is giving lower = 0 and upper = 247 ..May I know what I am doing wrong
It can give you lower = 0 and upper = 247 for Rx = 247, because ushort is a 16bit value, and 247 fits on 8 bits. That's why upper 8 bits are zero (not needed to hold 247) and lower bits are holding the whole number, which is 247 or 00000000 11110111 in binary.
The first number which will give you non-zero upper bits is 256 (00000001 00000000), for which:
upper = 1
lower = 0
To have upper = 47 you need to reverse the process, so let's write it as a 8 bit binary number: 00101111. Then put those 8 bits as upper bits of a 16 bit number: 00101111 00000000. Since you want lower = 2 we need to put 2 in in the right 8 bits. This gives 00101111 00000010 binary which is equal to 12034 decimal.
Not sure what you're trying to achieve, but for the code you've provided Rx = 12034 is the only possibility to have upper and lower equal to what you desire. So if that doesn't suit your protocol, then you've made a mistake somewhere else.
This is most probably the dumbest question anyone would ask, but regardless I hope I will find a clear answer for this.
My question is - How is an integer stored in computer memory?
In c# an integer is of size 32 bit. MSDN says we can store numbers from -2,147,483,648 to 2,147,483,647 inside an integer variable.
As per my understanding a bit can store only 2 values i.e 0 & 1. If I can store only 0 or 1 in a bit, how will I be able to store numbers 2 to 9 inside a bit?
More precisely, say I have this code int x = 5; How will this be represented in memory or in other words how is 5 converted into 0's and 1's, and what is the convention behind it?
It's represented in binary (base 2). Read more about number bases. In base 2 you only need 2 different symbols to represent a number. We usually use the symbols 0 and 1. In our usual base we use 10 different symbols to represent all the numbers, 0, 1, 2, ... 8, and 9.
For comparison, think about a number that doesn't fit in our usual system. Like 14. We don't have a symbol for 14, so how to we represent it? Easy, we just combine two of our symbols 1 and 4. 14 in base 10 means 1*10^1 + 4*10^0.
1110 in base 2 (binary) means 1*2^3 + 1*2^2 + 1*2^1 + 0*2^0 = 8 + 4 + 2 + 0 = 14. So despite not having enough symbols in either base to represent 14 with a single symbol, we can still represent it in both bases.
In another commonly used base, base 16, which is also known as hexadecimal, we have enough symbols to represent 14 using only one of them. You'll usually see 14 written using the symbol e in hexadecimal.
For negative integers we use a convenient representation called twos-complement which is the complement (all 1s flipped to 0 and all 0s flipped to 1s) with one added to it.
There are two main reasons this is so convenient:
We know immediately if a number is positive of negative by looking at a single bit, the most significant bit out of the 32 we use.
It's mathematically correct in that x - y = x + -y using regular addition the same way you learnt in grade school. This means that processors don't need to do anything special to implement subtraction if they already have addition. They can simply find the twos-complement of y (recall, flip the bits and add one) and then add x and y using the addition circuit they already have, rather than having a special circuit for subtraction.
This is not a dumb question at all.
Let's start with uint because it's slightly easier. The convention is:
You have 32 bits in a uint. Each bit is assigned a number ranging from 0 to 31. By convention the rightmost bit is 0 and the leftmost bit is 31.
Take each bit number and raise 2 to that power, and then multiply it by the value of the bit. So if bit number three is one, that's 1 x 23. If bit number twelve is zero, that's 0 x 212.
Add up all those numbers. That's the value.
So five would be 00000000000000000000000000000101, because 5 = 1 x 20 + 0 x 21 + 1 x 22 + ... the rest are all zero.
That's a uint. The convention for ints is:
Compute the value as a uint.
If the value is greater than or equal to 0 and strictly less than 231 then you're done. The int and uint values are the same.
Otherwise, subtract 232 from the uint value and that's the int value.
This might seem like an odd convention. We use it because it turns out that it is easy to build chips that perform arithmetic in this format extremely quickly.
Binary works as follows (as your 32 bits).
1 1 1 1 | 1 1 1 1 | 1 1 1 1 | 1 1 1 1 | 1 1 1 1 | 1 1 1 1 | 1 1 1 1 | 1 1 1 1
2^ 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16......................................0
x
x = sign bit (if 1 then negative number if 0 then positive)
So the highest number is 0111111111............1 (all ones except the negative bit), which is 2^30 + 2 ^29 + 2^28 +........+2^1 + 2^0 or 2,147,483,647.
The lowest is 1000000.........0, meaning -2^31 or -2147483648.
Is this what high level languages lead to!? Eeek!
As other people have said it's a base 2 counting system. Humans are naturally base 10 counters mostly, though time for some reason is base 60, and 6 x 9 = 42 in base 13. Alan Turing was apparently adept at base 17 mental arithmetic.
Computers operate in base 2 because it's easy for the electronics to be either on or off - representing 1 and 0 which is all you need for base 2. You could build the electronics in such a way that it was on, off or somewhere in between. That'd be 3 states, allowing you to do tertiary math (as opposed to binary math). However the reliability is reduced because it's harder to tell the difference between those three states, and the electronics is much more complicated. Even more levels leads to worse reliability.
Despite that it is done in multi level cell flash memory. In these each memory cell represents on, off and a number of intermediate values. This improves the capacity (each cell can store several bits), but it is bad news for reliability. This sort of chip is used in solid state drives, and these operate on the very edge of total unreliability in order to maximise capacity.
I'm writing up a QuadTree class and I need to include neighbor searches. I'm following along with this paper which includes a C implementation. (I'm basically converting it to C#.) And I'm having trouble because I'm not very good at working with binary numbers. I need to do the following things:
given #100 and #010, combine them to get #110. 1s will never overlap. right now what I do is store 100 and 10, when I add them it gives me 110.
perform left and right binary shifts on numbers like #011. right now I was storing 011 and applying the >> or << operator to it. This gives me completely the wrong number but strangely the logic I used it in to find common quad tree parents was working just fine.
given #011 and #001 sum them to get #100. Right now I'm storing 11 and 1, this obviously doesn't work at all
.
Perform bitwise subtraction, same as above but - instead of + :)
perform ANDs, ORs and XORs.
So, right now I'm storing everything as an integer that looks like the binary value, and the math seems to be working for the ANDs, ORs, XORs and shifts. The numbers are crazy in the middle but I get the right answer in the end.
I'm trying an implementation right now where I store the integer value that is the value of the binary number but I have to convert back and forth a lot, this is particularly a pain because I'm converting between an integer representation of the Value of the number and a string representation of the binary number itself. Creating a new string every second line of code is going to be a performance nightmare.
Can you guys recommend a basic strategy for working with binary numbers in C#?
P.S. I don't ever need to see the integer representation of these numbers. I really don't care that #010 == 2, the work I need to do sees it as #010 end of story.
Hopefully this is more clear than my original post!
I hope this will clear up some confusion:
The literal 0x00000001 represents 1 using hexadecimal notation.
The literal 1 represents 1 using decimal notation.
Here are some pairs of equivalent literals:
0x9 == 9
0xA == 10
0xF == 15
0x10 == 16
0x11 == 17
0x1F == 31
The primitive integral data types (byte, sbyte, ushort, short, char, uint, int, ulong, long) are are always stored in the computer's memory in binary format. Here are the above values notated with five bits:
1 == #00001
9 == #01001
10 == #01010
15 == #01111
16 == #10000
17 == #10001
31 == #11111
Now, consider:
unsigned int xLeftLocCode = xLocCode - 0x00000001;
Either of the following is equivalent in C#:
uint xLeftLocCode = xLocCode - 1;
uint xLeftLocCode = xLocCode - 0x00000001;
To assign the binary #10 to a uint variable, do this:
uint binaryOneZero = 2; //or 0x2
Hexadecimal notation is useful for bit manipulation because there is a one-to-one correspondence between hexadecimal and binary digits. More accurately, there is a one-to-four correspondence, as each of the 16 hexadecimal digits represents one of the 16 possible states of four bits:
0 == 0 == 0000
1 == 1 == 0001
2 == 2 == 0010
3 == 3 == 0011
4 == 4 == 0100
5 == 5 == 0101
6 == 6 == 0110
7 == 7 == 0111
8 == 8 == 1000
9 == 9 == 1001
A == 10 == 1010
B == 11 == 1011
C == 12 == 1100
D == 13 == 1101
E == 14 == 1110
F == 15 == 1111
It's therefore fairly easy to know that 0x700FF, for example, has all the bits of the least significant byte set, none of the next most significant byte, and the lower three bits of the next most significant byte. It's much harder to see that information at a glance if you use the literal 459007 to represent that value.
In conclusion:
Can you guys recommend a basic strategy for working with binary numbers in C#?
Learn the table above, and use hexadecimal literals.
why that line of interest does bitwise subtraction in C but integer subtraction in C#.
They should both do the same. Why do you think otherwise? And what do you mean with bitwise subtraction?
I'm storing the binary number 10 as the integer 10, not as the integer 2. I could be doing this all wrong.
Yes, That's wrong. #010 == 2, not 10.
I guess what I looking for is some basic strategy for working with binary numbers in C#.
By and large, those operations should be the same as in C.
The line you marked has nothing to do with bitwise anything. It's a straight subtraction of the number 1 (expressed as a hex double word (DWORD), or unsigned long integer (uint in C#).
Hey, I'm self-learning about bitwise, and I saw somewhere in the internet that arithmetic shift (>>) by one halfs a number. I wanted to test it:
44 >> 1 returns 22, ok
22 >> 1 returns 11, ok
11 >> 1 returns 5, and not 5.5, why?
Another Example:
255 >> 1 returns 127
127 >> 1 returns 63 and not 63.5, why?
Thanks.
The bit shift operator doesn't actually divide by 2. Instead, it moves the bits of the number to the right by the number of positions given on the right hand side. For example:
00101100 = 44
00010110 = 44 >> 1 = 22
Notice how the bits in the second line are the same as the line above, merely
shifted one place to the right. Now look at the second example:
00001011 = 11
00000101 = 11 >> 1 = 5
This is exactly the same operation as before. However, the result of 5 is due to the fact that the last bit is shifted to the right and disappears, creating the result 5. Because of this behavior, the right-shift operator will generally be equivalent to dividing by two and then throwing away any remainder or decimal portion.
11 in binary is 1011
11 >> 1
means you shift your binary representation to the right by one step.
1011 >> 1 = 101
Then you have 101 in binary which is 1*1 + 0*2 + 1*4 = 5.
If you had done 11 >> 2 you would have as a result 10 in binary i.e. 2 (1*2 + 0*1).
Shifting by 1 to the right transforms sum(A_i*2^i) [i=0..n] in sum(A_(i+1)*2^i) [i=0..n-1]
that's why if your number is even (i.e. A_0 = 0) it is divided by two. (sorry for the customised LateX syntax... :))
Binary has no concept of decimal numbers. It's returning the truncated (int) value.
11 = 1011 in binary. Shift to the right and you have 101, which is 5 in decimal.
Bit shifting is the same as division or multiplication by 2^n. In integer arithmetics the result gets rounded towards zero to an integer. In floating-point arithmetics bit shifting is not permitted.
Internally bit shifting, well, shifts bits, and the rounding simply means bits that fall off an edge simply getting removed (not that it would actually calculate the precise value and then round it). The new bits that appear on the opposite edge are always zeroes for the right hand side and for positive values. For negative values, one bits are appended on the left hand side, so that the value stays negative (see how two's complement works) and the arithmetic definition that I used still holds true.
In most statically-typed languages, the return type of the operation is e.g. "int". This precludes a fractional result, much like integer division.
(There are better answers about what's 'under the hood', but you don't need to understand those to grok the basics of the type system.)