Problems with large bool array in C# - c#
I decided to write a prime number generator as an easy excerise. The code is pretty simple:
static void generatePrimes (long min, long max)
{
bool[] prime = new bool[max + 1];
for (long i=2; i<max+1; i++)
prime [i] = true;
for (long i=2; i<max+1; i++) {
if (prime [i]) {
if (i>=min)
Console.WriteLine (i);
for (long j=i*2; j<max+1; j+=i)
prime [j] = false;
}
}
Console.WriteLine ();
}
It works just fine with input like 1..10000. However, around max=1000000000 it starts to work EXTREMELY slow; also, mono takes about 1Gb of memory. To me, it seems kinda strange: shouldn't the bool[1000000000] take 1000000000 bits, not bytes? Maybe I'm making some stupid mistake that I don't see that makes it so uneffective?
The smallest unit of information a computer can address is a byte. Thus a bool is stored as a byte. You will need special code to put 8 bools in one byte. The BitArray class does this for you.
Nope. Contrarily to C++'s vector<bool>, in C# an array of bool is, well, an array of bools.
If you want your values to be packed (8 bits per bool), use a BitArray instead.
Related
Differences in division and multiplication vs bit shifting
DISCLAIMER I do not want to know when or if to use shift operators in my code, I am interested in why multiplication is faster than shifting bits to the left whereas division is not. As I was just wandering around SO I came across this question regarding efficiency and speed of division and bit shifting. It basically states that although one might save a few seconds when performing bit shifts on powers of 2, it is not some difference one has to worry about. Intrigued by this I decided to check how much faster bit shifting in C# actually is and realised something strange: Bit shifting instead of dividing is faster, as I expected, but the "normal" multiplication method is faster than bit shifting. My question is simple: Why is the multiplication of two numbers faster than bit shifting, although bit shifting is a primitive operation for the processor? Here are the results for my test case: Division: | Multiplication: Bit shift: 315ms | 315ms normal: 406ms | 261ms The times are the averages of 100 cases with each case consisting of 10 operations per number on 10000000 random positive numbers ranging from 1 to int.MaxValue. The operations ranged from dividing/multiplying by 2 to 1024 (in powers of 2) and bit shifting from 1 to 10 digits. EDIT #usr: I am using .NET version 4.5.1 I updated my results because I realised I only computed a tenth of the numbers I stated... facepalm My Main: static Main(string[] args) { Fill(); // fills the array with random numbers Profile("division shift:", 100, BitShiftDiv); Profile("division:", 100, Div); Profile("multiplication shift:", 100, BitShiftMul); Profile("multiplication:", 100, Mul); Console.ReadKey(); } This is my profiling method: static void Profile(string description, int iterations, Action func) { GC.Collect() GC.WaitForPendingFinalizers(); GC.Collect(); func(); Stopwatch stopWatch = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { func(); } stopWatch.Stop(); Console.WriteLine(description); Console.WriteLine("total: {0}ms", stopWatch.Elapsed.TotalMilliseconds); Console.WriteLine(" avg: {0}ms", stopWatch.Elapsed.TotalMilliseconds / (double)iterations); } The Actions containing the operations are structured like this: static void <Name>() { for (int s = 1; s <= 10; s++) /* for shifts */ for (int s = 2; s <= 1024; s++) /* for others */ { for (int i = 0; i < nums.Length; i++) { var useless = nums[i] <shift> s; /* shifting */ var useless = nums[i] <operator> s; /* otherwise */ } } } nums is a public array containing 10000000 ints, which is filled by the Fill() method.
To sum up the answers already mentioned in the comments: Multiplication, as well as bit shifting, is faster because is a native operation for the CPU too. It takes one cycle while bit shifting takes about four which is why it is faster. Division takes something between 11 and 18 cycles. Using C# I cannot get close enough to the CPU to get diagnostically conclusive results because many optimizations take place between my code and the CPU. Also, microbenchmarking is hard and can produce erroneous results, which also can happen because of the above mentioned reason. If I forgot anything, please comment and tell me!
Parallelizing very large array base conversion
I have a method that converts value to a newBase number of length length. The logic in english is: If we calculated every possible combination of numbers from 0 to (c-1) with a length of x what set would occur at point i While the method below does work perfectly, because very large numbers are used, it can take a long time to complete: For example, value=(((65536^480000)-1)/2), newbase=(65536), length=(480000) takes about an hour to complete on a 64 bit architecture, quad core PC). private int[] GetValues(BigInteger value, int newBase, int length) { Stack<int> result = new Stack<int>(); while (value > 0) { result.Push((int)(value % newBase)); if (value < newBase) value = 0; else value = value / newBase; } for (var i = result.Count; i < length; i++) { result.Push(0); } return result.ToArray(); } My question is, how can I change this method into something that will allow multiple threads to work out part of the number? I am working C#, but if you're not familiar with that then pseudocode is fine too. Note: The method is from this question: Cartesian product subset returning set of mostly 0
If that GetValues method is really the bottleneck, there are several things you can do to speed it up. First, you're dividing by newBase every time through the loop. Since newBase is an int, and the BigInteger divide method divides by a BigInteger, you're potentially incurring the cost of an int-to-BigInteger conversion on every iteration. You might consider: BigInteger bigNewBase = newBase; Also, you can cut the number of divides in half by calling DivRem: while (value > 0) { BigInteger rem; value = BigInteger.DivRem(value, bigNewBase, out rem); result.Push((int)rem); } One other optimization, as somebody mentioned in comments, would be to store the digits in a pre-allocated array. You'll have to call Array.Reverse to get them in the proper order, but that takes approximately no time. That method, by the way, doesn't lend itself to parallelizing because computing each digit depends on the computation of the previous digit.
Variable "cluster" to count factorial in c#
Trying to count factorial of a big number, for example 1000! static void Main(string[] args) { UInt64 fact = 1; for (UInt64 i = 1000; i > 0; i--) { fact = fact * i; } Console.WriteLine(fact); //returns 0, due to overflow UInt64, max fact is 56! Console.ReadKey(); } So i ask, if there is some way to join more variables to cluster, so i can make really large variable to store "big" number.
You can use a BigInteger. This type can store integers of arbitrary size, until you run out of memory.
In .NET 4 BigInteger will do what you want. Big integers in C# may be of more interest as well since it is a very similar question (well, more a very similar answer).
how to manually calculate the memory been used
is there any way of calculate manually the memory that an array is goin to consume. i am using for languaje C# in a 64 bit OS let say i have the next array: int number[][]= new int[2][2]; number[0][0]=25; number[0][1]=60; .... ... so my fist question is, each dimension of the array has the same bit asignation? lets say number[0][0] has a 12 bit asing (i dont now if 12 bits is the right answer) so this will make the first line a 24 bit of memory asing? how much fisical and virtual memory does each dimension takes? if i use int, double or string for the array is there any diference of memory to been used? at the end if i used GC.GetTotalMemory will i recibe the same result of the total of memory been used by array?
You need to use the sizeof function to get how many bytes are allocated to your Type. int number[][] = new int[2][]; for (int i = 0; i < number.Length; i++) { number[i] = new int[2]; } int size = sizeof(int) * number.Length * number[0].Length;
1000 digit number in C#
I am working on Project Euler and ran into an issue. I am unable to use a 1000 digit number and wanted to know if I am doing something wrong or am just going about this solution in the wrong way and if so what would be best approach be? C# namespace ToThePowerOf { class Program { static void Main(string[] args) { BigInteger n = 1; int x = 0; BigInteger [] number; number = new BigInteger[149194]; number[x] = 1; number[x + 1] = 1; x = 3; ; BigInteger check = 10000000000000000000000000000 0000000000000000000000000000000 0000000000000000000000000000000 0000000000000000000000000000000 0000000000000000000000000000000 0000000000000000000000000000000 0000000000000000000000000000000 0000000000000000000000000000000 0000000000000000000000000000000 00000000000000000000000; for (int i = 99; i > 0; i--) { n = (n - 1) + (n - 2); number[x] = n; x++; if (n > check) { Console.WriteLine(x); } } } } }
I'm guessing the 'issue' you ran into (would be helpful to include error message) is that the compiler doesn't like the integer literal with 1000 digits so you can't initialise it with a very large integer literal. As others have noted, breaking the integer literal into multiple lines isn't valid either. The number[x] = 1; lines work because the compiler can handle the integer literal 1 and because we're assigning it to a BigInteger it uses BigInteger's implicit operator to convert it to a BigInteger. One simple method to get around your problem with the big integer literal is to use the BigInteger.Parse method to create your 1000 digit number. BigInteger check = BigInteger.Parse("10000....", CultureInfo.InvariantCulture); Another method could be to initialise it with a small int, then use maths to get to the number you want, as in Jon Skeet's answer.
There's no literal support for BigInteger in C#. So while using BigInteger isn't incorrect, you'll need to work out a different way of instantiating it - e.g. new BigInteger(10).Pow(1000).
Such a big literal isn't possible. Integer literals can be at most 64 bits. To get a large biginteger, you can either convert from string, or calculate the number instead of hardcoding it. In your case calculating it with BigInteger.Pow(10, digits) is the cleanest solution.
I'm still unsure on the BigInteger handling in C#, however on the Project Euler question you refer to. You can read the number in letter by letter from a text file and convert to an int. Then do the multiplications and checks. Not elegant but it works! See http://msdn.microsoft.com/en-us/library/system.io.filestream.aspx for syntax ref.
I'm probably really late on this, but what I did was take every number and make it a separate object within an array. I then took the first 5 numbers of the array and multiplied them together and set them to a variable. If they were greater than the max, I set it to the max. I then went on to the next set for numbers 1-6 and did the same etc. I did get an out of range exception. In which case you use a try and get format until you receive this exception. If you want to see the code, I will edit my response, but to save you time on the array, if you still want to attempt this, I will give you the array. long[] a; a = new long[] { 7,3,1,6,7,1,7,6,5,3,1,3,3,0,6,2,4,9,1,9,2,2,5,1,1,9,6,7,4,4,2,6,5,7,4,7,4,2,3,5,5,3,4,9,1,9,4,9,3,4, 9,6,9,8,3,5,2,0,3,1,2,7,7,4,5,0,6,3,2,6,2,3,9,5,7,8,3,1,8,0,1,6,9,8,4,8,0,1,8,6,9,4,7,8,8,5,1,8,4,3, 8,5,8,6,1,5,6,0,7,8,9,1,1,2,9,4,9,4,9,5,4,5,9,5,0,1,7,3,7,9,5,8,3,3,1,9,5,2,8,5,3,2,0,8,8,0,5,5,1,1, 1,2,5,4,0,6,9,8,7,4,7,1,5,8,5,2,3,8,6,3,0,5,0,7,1,5,6,9,3,2,9,0,9,6,3,2,9,5,2,2,7,4,4,3,0,4,3,5,5,7, 6,6,8,9,6,6,4,8,9,5,0,4,4,5,2,4,4,5,2,3,1,6,1,7,3,1,8,5,6,4,0,3,0,9,8,7,1,1,1,2,1,7,2,2,3,8,3,1,1,3, 6,2,2,2,9,8,9,3,4,2,3,3,8,0,3,0,8,1,3,5,3,3,6,2,7,6,6,1,4,2,8,2,8,0,6,4,4,4,4,8,6,6,4,5,2,3,8,7,4,9, 3,0,3,5,8,9,0,7,2,9,6,2,9,0,4,9,1,5,6,0,4,4,0,7,7,2,3,9,0,7,1,3,8,1,0,5,1,5,8,5,9,3,0,7,9,6,0,8,6,6, 7,0,1,7,2,4,2,7,1,2,1,8,8,3,9,9,8,7,9,7,9,0,8,7,9,2,2,7,4,9,2,1,9,0,1,6,9,9,7,2,0,8,8,8,0,9,3,7,7,6, 6,5,7,2,7,3,3,3,0,0,1,0,5,3,3,6,7,8,8,1,2,2,0,2,3,5,4,2,1,8,0,9,7,5,1,2,5,4,5,4,0,5,9,4,7,5,2,2,4,3, 5,2,5,8,4,9,0,7,7,1,1,6,7,0,5,5,6,0,1,3,6,0,4,8,3,9,5,8,6,4,4,6,7,0,6,3,2,4,4,1,5,7,2,2,1,5,5,3,9,7, 5,3,6,9,7,8,1,7,9,7,7,8,4,6,1,7,4,0,6,4,9,5,5,1,4,9,2,9,0,8,6,2,5,6,9,3,2,1,9,7,8,4,6,8,6,2,2,4,8,2, 8,3,9,7,2,2,4,1,3,7,5,6,5,7,0,5,6,0,5,7,4,9,0,2,6,1,4,0,7,9,7,2,9,6,8,6,5,2,4,1,4,5,3,5,1,0,0,4,7,4, 8,2,1,6,6,3,7,0,4,8,4,4,0,3,1,9,9,8,9,0,0,0,8,8,9,5,2,4,3,4,5,0,6,5,8,5,4,1,2,2,7,5,8,8,6,6,6,8,8,1, 1,6,4,2,7,1,7,1,4,7,9,9,2,4,4,4,2,9,2,8,2,3,0,8,6,3,4,6,5,6,7,4,8,1,3,9,1,9,1,2,3,1,6,2,8,2,4,5,8,6, 1,7,8,6,6,4,5,8,3,5,9,1,2,4,5,6,6,5,2,9,4,7,6,5,4,5,6,8,2,8,4,8,9,1,2,8,8,3,1,4,2,6,0,7,6,9,0,0,4,2, 2,4,2,1,9,0,2,2,6,7,1,0,5,5,6,2,6,3,2,1,1,1,1,1,0,9,3,7,0,5,4,4,2,1,7,5,0,6,9,4,1,6,5,8,9,6,0,4,0,8, 0,7,1,9,8,4,0,3,8,5,0,9,6,2,4,5,5,4,4,4,3,6,2,9,8,1,2,3,0,9,8,7,8,7,9,9,2,7,2,4,4,2,8,4,9,0,9,1,8,8, 8,4,5,8,0,1,5,6,1,6,6,0,9,7,9,1,9,1,3,3,8,7,5,4,9,9,2,0,0,5,2,4,0,6,3,6,8,9,9,1,2,5,6,0,7,1,7,6,0,6, 0,5,8,8,6,1,1,6,4,6,7,1,0,9,4,0,5,0,7,7,5,4,1,0,0,2,2,5,6,9,8,3,1,5,5,2,0,0,0,5,5,9,3,5,7,2,9,7,2,5, 7,1,6,3,6,2,6,9,5,6,1,8,8,2,6,7,0,4,2,8,2,5,2,4,8,3,6,0,0,8,2,3,2,5,7,5,3,0,4,2,0,7,5,2,9,6,3,4,5,0 };