Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Does C# have a 4 bit data type? I want to make a program with variables that waste the minimum amount of memory, because the program will consume a lot.
For example: I need to save a value that i know it will go from 0 to 10 and a 4 bit var can go from 0 to 15 and it's perfect. But the closest i found was the 8 bit (1 Byte) data type Byte.
I have the idea of creating a c++ dll with a custom data type. Something like nibble. But, if that's the solution to my problem, i don't know where to start, and what i have to do.
Limitations: Creating a Byte and splitting it in two is NOT an option.
No, there is no such thing as a four-bit data type in c#.
Incidentally, four bits will only store a number from 0 to 15, so it doesn't sound like it is fit for purpose if you are storing values from 0 to 127. To compute the range of a variable given that it has N bits, use the formula (2^N)-1 to calculate the maximum. 2^4 = 16 - 1 = 15.
If you need to use a data type that is less than 8 bits in order to save space, you will need to use a packed binary format and special code to access it.
You could for example store two four-bit values in a byte using an AND mask plus a bit shift, e.g.
byte source = 0xAD;
var hiNybble = (source & 0xF0) >> 4; //Left hand nybble = A
var loNyblle = (source & 0x0F); //Right hand nybble = D
Or using integer division and modulus, which works well too but maybe isn't quite as readable:
var hiNybble = source / 16;
var loNybble = source % 16;
And of course you can use an extension method.
static byte GetLowNybble(this byte input)
{
return input % 16;
}
static byte GetHighNybble(this byte input)
{
return input / 16;
}
var hiNybble = source.GetHighNybble();
var loNybble = source.GetLowNybble();
Storing it is easier:
var source = hiNybble * 16 + lowNybble;
Updating just one nybble is harder:
var source = source & 0xF0 + loNybble; //Update only low four bits
var source = source & 0x0F + (hiNybble << 4); //Update only high bits
A 4-bit data type (AKA Nib) only goes from 0-15. It requires 7 bits to go from 0-127. You need a byte essentially.
No, C# does not have a 4-bit numeric data type. If you wish to pack 2 4-bit values in a single 8-bit byte, you will need to write the packing and unpacking code yourself.
No, even boolean is 8 bits size.
You can use >> and << operators to store and read two 4 bit values from one byte.
https://msdn.microsoft.com/en-us/library/a1sway8w.aspx
https://msdn.microsoft.com/en-us/library/xt18et0d.aspx
Depending on how many of your nibbles you need to handle and how much of an issue performance is over memory usage, you might want to have a look at the BitArray and BitVector32 classes. For passing around of values, you'd still need bigger types though.
Yet another option could also be StructLayout fiddling, ... beware of dragons though.
Related
I want to set the last 4 bits of my byte list to 0. I've tried this line of code but it does not work:
myData = 1111.1111
myData should be = 1111.0000
(myData & 0x0F) >> 4
Assuming you mean that "4 last bits" is 4 least significant bits, I have this code example for you:
var myData = 0xFF;
var result = myData & ~0xF;
So, basically, what you want here is not to set the 4 least significant bits to 0, but to preserve the rest of the data. To achieve this you have to prepare the "passthrough" mask, which matches the criteria, this is the one's complement of the non-needed bits mask i.e. the one's complement of the 0xF (also note that 0xF = (2 to the power of 4) - 1 -- where 4 is the number of the desired cleared out LSBs). Thus, ~0xF is the desired mask -- you just have to apply it to the number -- myData & ~0xF.
N.B. The one's complement approach is better than magical numbers, pre-computed yourself (such as 0xF in the anwser above), as the compiler will generate the valid number of MSBs (most significant bits) for the type you use this approach against.
An even safer approach would be to compute the one's complement of the variable itself, giving the effective code stated below:
var myData = 0xFF;
var result = ~(~myData | 0xF);
That's it!
To preserve the 4 high bits and zero the 4 low bits
myData & 0xF0
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
In counting the number of bits in a word, a brute force would be something like this:
int CountNumSetBits(unsigned long n)
{
unsigned short num_setbits = 0;
while (n)
{
num_setbits += n & 1;
n >>= 1;
}
return num_setbits;
}
The big O speed would be O(n) where n is the number of bits in the Word.
I thought of another way of writing the algorithm taking advantage of the fact that we an optain the first occurance of a set bit using y = x&~(x-1)
int CountNumSetBitsMethod2(unsigned long n)
{
unsigned short num_setbits = 0;
int y = 0;
while (n)
{
y = n& ~(n - 1); // get first occurrence of '1'
if (y) // if we have a set bit inc our counter
++num_setbits;
n ^=y; // erase the first occurrence of '1'
}
return num_setbits;
}
If we assume that are inputs are 50% 1's and 50% 0's it appears that the second algorithm could be twice as fast. However, the actual complexity is greater:
In method one we do the following for each bit:
1 add
1 and
1 shift
In method two we do the following for each set bit:
1 and
1 complement
1 subtraction (the result of the subtraction has to be copied to another reg)
1 compare
1 increment (if compare is true)
1 XOR
Now, in practice one can determine which algorithm is faster by performing some profiling. That is, using a stop watch mechanism and some test data and call each algorithm say a million times.
What I want to do first, however, is see how well I can estimate the speed difference by eyeballing the code (given same number of set and unset bits).
If we assume that the subtraction takes the same amount cycles as the add (approximately), and all the other operations are equal cycle wise, can one conclude that each algorithm takes about the same amount of time?
Note: I am assuming here we cannot use lookup tables.
The second algorithm can be greatly simplified:
int CountNumSetBitsMethod2(unsigned long n) {
unsigned short num_setbits = 0;
while (n) {
num_setbits++;
n &= n - 1;
}
return num_setbits;
}
There are many more ways to compute the number of bits set in a word:
Using lookup tables for mutiple bits at a time
Using 64-bit multiplications
Using parallel addition
Using extra tricks to shave a few cycles.
Trying to determine empirically which is faster by counting cycles is not so easy because even looking at the assembly output, it is difficult to assess the impact of instruction parallelisation, pipelining, branch prediction, register renaming and contention... Modern CPUs are very sophisticated! Furthermore, the actual code generated depends on the compiler version and configuration and the timings depend on the CPU type and release... Not to mention the variability linked to the particular sets of values used (for algorithms with variable numbers of instructions).
Benchmarking is a necessary tool, but even careful benchmarking may fail to model the actual usage correctly.
Here is a great site for this kind of bit twiddling games:
http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive
I suggest you implement the different versions and perform comparative benchmarks on your system. There is no definite answer, only local optima for specific sets of conditions.
Some amazing finds:
// option 3, for at most 32-bit values in v:
c = ((v & 0xfff) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f;
c += (((v & 0xfff000) >> 12) * 0x1001001001001ULL & 0x84210842108421ULL) %
0x1f;
c += ((v >> 24) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f;
A more classic one, usually considered the best method for counting bits in a 32-bit integer v:
v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
first, the only way to know how fast things are is to measure them.
Second - to find the number of set bits in some bytes, build a lookup table for the number of set bits in a byte
0->0
1->1
2->1
3->2
4->1
etc.
This is a common method and very fast
You can code it by hand or create it at startup
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
So for my computer architecture class I have to simulate a cache/memory relationship on C# and I'm just not sure how a cache actually stores data. I get the concept of a cache tag, but I really don't get the offset.
So say I have an RAM that holds 256 32bit integers. I want to have a caching system where I have a cache that holds 8 32bit integers. But then in those 32bit integers in the cache I need to add the tag and valid bit, which makes it roughly sized down to 26 bits or so. So how can I store the 32 bit data in that remaining 26 bits?
Here is the code I have right now, it's still a work in progress
class Memory
{
public List<UInt32> instructions = new List<UInt32>();
const int directCacheSize = 8;
ulong[] directCache = new ulong[directCacheSize];
private int[] stack = new int[256];
public int this[int i]
{
get
{
int directMapIndex = i % directCacheSize;
if (directCache[directMapIndex] == Convert.ToUInt64(stack[i]))
{
return Convert.ToInt32(directCache[directMapIndex] - 18446744069414584320);
}
else
{
directCache[directMapIndex] = (Convert.ToUInt64(i) << 32) + Convert.ToUInt64(stack[i]);
return stack[i];
}
}
set
{
stack[i] = value;
}
}
}
I've been trying to understand this mostly incoherent question and I think I've got it.
I was thinking originally that your fundamental error is that bits used to maintain the cache data structure bits are subtracted from the data size; that doesn't make any sense. They are added to the data size.
But then I realized that no, your fundamental error is that you have confused bits with bytes. You are subtracting six bits from 32 bytes to nonsensically get 26, but you should be adding six bits to 32 x 8 bits.
The error that is just plain confusing is that you also seem to have confused the offset into the data block with the data block itself. The data block stores the data. The offset identifies the location of the relevant data within the data block. The offset is part of an effective address, not a cache line!
You also seem to have forgotten about the dirty bit throughout.
So then a single block in my direct map cache would look like this: [tag 5bit][data 32bit]
No. The number of times that 32 appears in this problem has confused you deeply:
eight 32 bit words is 32 bytes
five bits can represent 32 possible tags
If you have 32 tags and 1024 bytes then each tag identifies 32 bytes
That's a lot of 32s and you've confused them terribly.
Start over.
Suppose you want a single line with 8 32 bit words in it, for a total of 32 bytes. What has to be in the single cache line?
the 32 bytes -- NOT BITS
a tag identifying where the 32 bytes came from
one validity bit
one dirty bit
If we assume that the 32 bytes can only be on 32-byte boundaries, and there are 1024 / 32 = 32 such boundaries, then for the tag we need log2(32) = 5 bits, so the total cache line size would be:
32 bytes NOT BITS of data
5 bits of tag
one validity bit
one dirty bit
Make sense?
I am currently developing a C# 2D sandbox based game. The game world is filled with tiles/blocks. Since the world is so large the game can sometimes use more than what is allowed for 32-bit application.
My tiles consist of the following data inside a struct:
public byte type;
public byte typeWall;
public byte liquid;
public byte typeLiquid;
public byte frameX;
public byte frameY;
public byte frameWallX;
public byte frameWallY;
I am looking to encapsulate all this data within one "long" (64-bit integer).
I want properties to get and set each piece of data using bit shifting, etc... (I have never done this).
Would this save space? Would it increase processing speed? If so how can it be accomplished?
Thanks.
I am looking to encapsulate all this data within one "long" (64-bit integer).
You can use StructLayoutAttribute with LayoutKind.Explicit and then decorate fields with FieldOffsetAttribute specifying the exact position.
I want properties to get and set each piece of data using bit shifting, etc... (I have never done this).
Then use shift left (<<), shift right (>>) and masking (and && to extract / or || to write (don't forget about any non-zero bits in the target byte)) with 0xff to separate individual bytes. Read more about bitwise operations here.
Would this save space? Would it increase processing speed?
Did you measure it? Did you discover a performace / memory consuption problem? If yes, go optimize it. If not, do not do premature optimizations. In other words, don't blindly try without measuring first.
I don't know why you want to do this, but you can do it in this way:
byte type = 4;
byte typeWall = 45;
byte liquid = 45;
byte typeLiquid = 234;
byte frameX = 23;
byte frameY = 23;
byte frameWallX = 22;
byte frameWallY = 221;
byte[] bytes = new [] {type, typeWall, liquid, typeLiquid, frameX, frameY, frameWallX, frameWallY};
BitConverter.ToInt64(bytes, 0);
or using << (shift) operator.
As you can see by pasting the following code into linqpad :
void Main()
{
sizeof(byte).Dump("byte size");
sizeof(Int32).Dump("int 32");
sizeof(Int64).Dump("int 64");
sizeof(char).Dump("for good measure, a char:");
}
You'll get:
byte size 1
int 32 4
int 64 8
for good measure, a char: 2
So packing 8 bytes in an int64 will be the same, but you'll have to play with the bits yourself (if that's your thing, by all means, go for it :)
I have come across a problem I cannot seem to solve.
I have a type of file "ASDF", and in their header I can get the necessary information to read them. The problem is that one of the "fields" is only 4 bits long.
So, lets say it's like this:
From bit 0 to 8 it's the index of the current node (I've read this already)
From 8 to 16 it's the index for the next node (Read this as well)
From bit 16 to 20 Length of the content (string, etc..)
So my problem is that if I try to read the "length" with a bytereader I will be losing 4 bits of information, or would be "4 bits off". Is there any way to read only 4 bits?
You should read this byte as you read the others then apply a bitmask of 0x0F
For example
byte result = (byte)(byteRead & 0x0F);
this will preserve the lower four bits in the result.
if the needed bits are the high four then you could apply the shift operator
byte result = (byte)((byteRead & 0x0F) >> 5);