How do I avoid stackoverflowexception within a finite loop (C#) - c#

I'm trying to write a code to find prime numbers within a given range. Unfortunately I'm running into some problems with too many repetitions that'll give me a stackoverflowexception after prime nr: 30000. I have tried using a 'foreach' and also not using a list, (doing each number as it comes) but nothing seems to handle the problem in hand.
How can I make this program run forever without causing a stackoverflow?
class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
List<double> Primes = new List<double>();
const double Start = 0;
const double End = 100000;
double counter = 0;
int lastInt = 0;
for (int i = 0; i < End; i++)
Primes.Add(i);
for (int i =0;i< Primes.Count;i++)
{
lastInt = (int)Primes[i] - RoundOff((int)Primes[i]);
Primes[i] = (int)CheckForPrime(Primes[i], Math.Round(Primes[i] / 2));
if (Primes[i] != 0)
{
Console.Write(", {0}", Primes[i]);
counter++;
}
}
stopwatch.Stop();
Console.WriteLine("\n\nNumber of prime-numbers between {0} and {1} is: {2}, time it took to calc this: {3} (millisecounds).\n\n" +
" The End\n", Start, End, counter, stopwatch.ElapsedMilliseconds);
}
public static double CheckForPrime(double Prim, double Devider)
{
if (Prim / Devider == Math.Round(Prim / Devider))
return 0;
else if (Devider > 2)
return CheckForPrime(Prim, Devider - 1);
else
return Prim;
}
public static int RoundOff(int i)
{
return ((int)Math.Floor(i / 10.0)) * 10;
}
}

Related

Why is the stopwatch not timing my method correctly?

I am trying to test the performance difference of my quicksort and mergesort methods, but for some reason the first cycle of the loop always show exactly 0.003 milliseconds and the rest 0 milliseconds.
public static void RunDiagnostics(int[] rangeOfLengthsToTest, int numOfTestsPerLength)
{
Stopwatch stopwatch = new Stopwatch();
int[] array;
double totalQuicksortTime, totalMergesortTime;
for (int i = rangeOfLengthsToTest[0]; i <= rangeOfLengthsToTest[1]; i++)
{
totalQuicksortTime = 0;
totalMergesortTime = 0;
for (int k = 0; k < numOfTestsPerLength; k++)
{
array = GetArray(i, new int[] { -9999, 9999 });
stopwatch.Start();
QuickSort((int[])array.Clone());
stopwatch.Stop();
totalQuicksortTime += stopwatch.ElapsedMilliseconds;
stopwatch.Restart();
MergeSort((int[])array.Clone());
stopwatch.Stop();
totalMergesortTime += stopwatch.ElapsedMilliseconds;
}
Console.WriteLine($"Quicksort took an average of {totalQuicksortTime / numOfTestsPerLength} milliseconds to sort arrays with a length of {i}.");
Console.WriteLine($"Mergesort took an average of {totalMergesortTime / numOfTestsPerLength} milliseconds to sort arrays with a length of {i}.");
Console.WriteLine();
}
}
Even when I print the elapsed milliseconds of each run instead of averaging them out, it still only times zeros.
edit: Here are my methods (sorry if they are a bit junk):
static void Main(string[] args)
{
RunDiagnostics(new int[] { 3, 12 }, 1000);
}
public static int[] GetArray(int length, int[] RangeOfNumbers)
{
Random rng = new Random();
int[] arr = new int[length];
for (int i = 0; i < arr.Length; i++)
arr[i] = rng.Next(RangeOfNumbers[0], RangeOfNumbers[1]);
return arr;
}
public static void QuickSort(int[] array)
{
QuickSort(0, array.Length - 1);
void QuickSort(int left, int right)
{
if (right > left)
{
if (right - left == 1)
{
if (array[left] > array[right])
Swap(left, right);
}
else
{
Swap(GetStartingPivotIndex(), right);
int pivot = Partition(left, right - 1);
QuickSort(left, pivot - 1);
QuickSort(pivot + 1, right);
}
}
int GetStartingPivotIndex()
{
if (array[left] > array[right])
{
if (array[left + (right - left) / 2] > array[right])
return right;
else
return left + (right - left) / 2;
}
else
{
if (array[left + (right - left) / 2] > array[left])
return left;
else
return left + (right - left) / 2;
}
}
int Partition(int low, int high)
{
while (low != high)
{
if (array[low] < array[right])
low++;
else if (array[high] > array[right])
high--;
else
Swap(low, high);
}
Swap(low, right);
return low;
}
void Swap(int index1, int Index2)
{
int temp = array[index1];
array[index1] = array[Index2];
array[Index2] = temp;
}
}
}
public static void MergeSort(int[] array)
{
MergeSort(array);
int[] MergeSort(int[] array)
{
int[] array1 = array.Take(array.Length / 2).ToArray();
int[] array2 = array.Skip(array.Length / 2).ToArray();
if (array1.Length > 1)
MergeSort(array1);
if (array2.Length > 1)
MergeSort(array2);
int c1 = 0;
int c2 = 0;
bool flag1 = false;
bool flag2 = false;
for (int i = 0; i < array.Length; i++)
{
if (flag1 && !flag2)
{
array[i] = array2[c2];
if (c2 == array2.Length - 1)
flag2 = true;
else c2++;
}
else if (flag2 && !flag1)
{
array[i] = array1[c1];
if (c1 == array1.Length - 1)
flag1 = true;
else c1++;
}
else if (!flag1 && !flag2)
{
if (array1[c1] < array2[c2])
{
array[i] = array1[c1];
if (c1 == array1.Length - 1)
flag1 = true;
else c1++;
}
else
{
array[i] = array2[c2];
if (c2 == array2.Length - 1)
flag2 = true;
else c2++;
}
}
}
return array;
}
}
This isn't a problem with the Stopwatch.
The very first time your sort code runs, it's taking much longer than subsequent times. This can happen due to JIT compilation, caching, and similar things that are completely outside of your control. It's taking long enough that the ElapsedMilliseconds value has a meaningful integer value (e.g. 3), and so when you divide it by 1000 you end up with a number in the thousands place (e.g. .003).
Every other time the sort code runs, it's taking less than a millisecond. So all the += operations are adding zero to the total. The sum of all those zeroes is zero.
Changing the += stopwatch.ElapsedMilliseconds to += stopwatch.Elapsed.TotalMilliseconds; will fix that particular problem, and give you results more like this:
Quicksort took an average of 0.003297300000000042 milliseconds to sort arrays with a length of 3.
Mergesort took an average of 0.0019986999999999453 milliseconds to sort arrays with a length of 3.
Quicksort took an average of 0.0013175999999999856 milliseconds to sort arrays with a length of 4.
Mergesort took an average of 0.001030500000000005 milliseconds to sort arrays with a length of 4.
Quicksort took an average of 0.001468300000000015 milliseconds to sort arrays with a length of 5.
Mergesort took an average of 0.0011402999999999956 milliseconds to sort arrays with a length of 5.
However, there are other issues to fix.
You're including the time spent cloning the array in your results.
Start() should be switched to Restart(): right now the nth run of QuickSort is including the n-1th run of Mergesort in its time.
The whole strategy of adding thousands of individual run times together still exposes you to rounding errors: they're just smaller with double than they are with int. You see all those 0000000s and 999999s in the results? A better strategy is typically to run the same sort a whole bunch of times and then see how much total time has passed.
In general, you're better off relying on a benchmarking framework rather than writing your own code. There are a lot of issues like these that you are unlikely to consider when writing your own.
As #JosephDaSilva pointed out, stopwatch.ElapsedMilliseconds returns an integer value which means it's going to round down to 0 if it was less then a milisecond. stopwatch.Elapsed.TotalMilliseconds should be used as it returns a floating-point value, which won't get rounded down.

Calculate how long it will take a loop to finish

So I have the following loop:
for (int i = 1; i < numRows + 2; i++) //numRows was +4, now +2
{
Console.Clear();
Console.WriteLine("Number of rows: " + numRows);
Console.Write("Checking Row #: " + currRowNumber);
//We want to skip every row that is null and continue looping until we have more than 3 rows in a row that are null, then break
if (i > 1) {
i -= 1;
}
//Create Worksheet Range
Microsoft.Office.Interop.Excel.Range range = (Microsoft.Office.Interop.Excel.Range) excelWorkbookWorksheet.Cells[i, 2];
string cellValue = Convert.ToString(range.Value);
if (nullCounter == 3) //was 5
{
Console.WriteLine("\nNull row detected...breaking");
Console.WriteLine("Number of rows deleted: " + numRowsDeleted);
break;
}
if (cellValue != null) {
if (cellValue.Contains(searchText)) {
//Console.WriteLine("Deleting Row: " + Convert.ToString(cellValue));
((Range) excelWorkbookWorksheet.Rows[i]).Delete(XlDeleteShiftDirection.xlShiftUp);
numRowsDeleted++;
//Console.WriteLine("Number of rows deleted: " + numRowsDeleted);
nullCounter = 0;
i--;
currRowNumber++;
rowsPerSecond = i;
} else {
currRowNumber++;
nullCounter = 0;
}
} else {
nullCounter++;
//Console.WriteLine("NullCounter: " + nullCounter);
}
i++;
}
I want to calculate how many rows I'm looping through per second, then calculate from that number how long it will take to complete the entire loop, based on how many rows there are.
Check out setting up a Stopwatch at the beginning of the loop and check its Elapsed property at the end.
Its pretty trivial to get something simple up and running. Consider the following class:
public class TimePredictor
{
private readonly Stopwatch watch = new Stopwatch();
private double currentProgressRate;
public void Start() => watch.Restart();
public void Stop() => watch.Stop();
public double ElapsedTime => watch.ElapsedMilliseconds;
public void Update(long currentProgress)
{
currentProgressRate = watch.ElapsedMilliseconds / (double)currentProgress;
}
public double GetExpectedTotalTime(long total)
=> total * currentProgressRate;
public double GetExpectedTimeLeft(long total)
=> GetExpectedTotalTime(total) - watch.ElapsedMilliseconds;
}
And a trivial use case:
var repetitions = 200;
var predictor = new TimePredictor();
predictor.Start();
for (int i = 0; i < repetitions; i++)
{
Thread.Sleep((new Random()).Next(100, 250));
if (i % 5 == 0)
{
predictor.Update(i);
Console.WriteLine($"Iteration #{i}:");
Console.WriteLine($"\tExpected total time: {predictor.GetExpectedTotalTime(repetitions) / 1000.0:N1}");
Console.WriteLine($"\tExpected time left: {predictor.GetExpectedTimeLeft(repetitions) / 1000.0:N1}");
Console.WriteLine();
}
}
predictor.Stop();
Console.WriteLine($"Total time: {predictor.ElapsedTime / 1000.0:N1}");
You have 2 possible solutions:
Take the StopWatch and a Counter. Start the sw before you start with looping and increase the counter with ervery loop. At the end of a walktrough of the loop you can divide counter / sw.Elapsed
Use a Counter and a Timer with an interval of 1000ms. Increase the counter every time you go though the For-loop. With every tick you get the current Loops / Second.
EDIT: When you are finished with the for-loop stop the Timer and the StopWatch

Output giving multiple values of each number when they should be single values

I'm learning C and C#. This question is for C#. This code from a book I'm reading gives the wrong output. The picture in the book gives output of only one instance of each number, but my code gives multiple instances of each number output. Is it something wrong with my computer?
Here is the class code:
namespace practice_6
{
public class Primes
{
private long min;
private long max;
public Primes()
: this(2, 100)
{
}
public Primes(long minimum, long maximum)
{
if (min < 2)
min = 2;
else
min = minimum;
max = maximum;
}
public IEnumerator GetEnumerator()
{
for (long possiblePrime = min; possiblePrime <= max; possiblePrime++)
{
bool isPrime = true;
for (long possibleFactor = 2; possibleFactor <= (long)Math.Floor(Math.Sqrt(possiblePrime)); possibleFactor++)
{
long remainderAfterDivision = possiblePrime % possibleFactor;
if (remainderAfterDivision == 0)
{
isPrime = false;
break;
}
if (isPrime)
{
yield return possiblePrime;
}
}
}
}
}
}
Here is the code from main:
static void Main(string[] args)
{
Primes primesFrom2To1000 = new Primes(2, 1000);
foreach (long i in primesFrom2To1000)
Console.Write("{0} ", i);
Console.ReadKey();
Here is the output:
Move the if (isPrime) part out of the factoring loop. (It's easier to notice things like this if you create a separate bool isPrime(int n) method.)

Precise alternative to Thread.Sleep

I have a method Limit() which counts a bandwidth passed thought some channel in certain time and limits by using Thread.Sleep() it (if bandwidth limit is reached).
Method itself produces proper ( in my opinion results ) but Thread.Sleep doesn't ( due to multithreaded CPU usage ) because i have proper "millisecondsToWait" but speed check afterwards is far from limitation i've passed.
Is there a way to make limitation more precise ?
Limiter Class
private readonly int m_maxSpeedInKbps;
public Limiter(int maxSpeedInKbps)
{
m_maxSpeedInKbps = maxSpeedInKbps;
}
public int Limit(DateTime startOfCycleDateTime, long writtenInBytes)
{
if (m_maxSpeedInKbps > 0)
{
double totalMilliseconds = DateTime.Now.Subtract(startOfCycleDateTime).TotalMilliseconds;
int currentSpeedInKbps = (int)((writtenInBytes / totalMilliseconds));
if (currentSpeedInKbps - m_maxSpeedInKbps > 0)
{
double delta = (double)currentSpeedInKbps / m_maxSpeedInKbps;
int millisecondsToWait = (int)((totalMilliseconds * delta) - totalMilliseconds);
if (millisecondsToWait > 0)
{
Thread.Sleep(millisecondsToWait);
return millisecondsToWait;
}
}
}
return 0;
}
Test Class which always fails in large delta
[TestMethod]
public void ATest()
{
List<File> files = new List<File>();
for (int i = 0; i < 1; i++)
{
files.Add(new File(i + 1, 100));
}
const int maxSpeedInKbps = 1024; // 1MBps
Limiter limiter = new Limiter(maxSpeedInKbps);
DateTime startDateTime = DateTime.Now;
Parallel.ForEach(files, new ParallelOptions {MaxDegreeOfParallelism = 5}, file =>
{
DateTime currentFileStartTime = DateTime.Now;
Thread.Sleep(5);
limiter.Limit(currentFileStartTime, file.Blocks * Block.Size);
});
long roundOfWriteInKB = (files.Sum(i => i.Blocks.Count) * Block.Size) / 1024;
int currentSpeedInKbps = (int) (roundOfWriteInKB/DateTime.Now.Subtract(startDateTime).TotalMilliseconds*1000);
Assert.AreEqual(maxSpeedInKbps, currentSpeedInKbps, string.Format("maxSpeedInKbps {0} currentSpeedInKbps {1}", maxSpeedInKbps, currentSpeedInKbps));
}
I used to use Thread.Sleep a lot until I discovered waithandles. Using waithandles you can suspend threads, which will come alive again when the waithandle is triggered from elsewhere, or when a time threshold is reached. Perhaps it's possible to re-engineer your limit methodology to use waithandles in some way, because in a lot of situations they are indeed much more precise than Thread.Sleep?
You can do it fairly accurately using a busy wait, but I wouldn't recommend it. You should use one of the multimedia timers to wait instead.
However, this method will wait fairly accurately:
void accurateWait(int millisecs)
{
var sw = Stopwatch.StartNew();
if (millisecs >= 100)
Thread.Sleep(millisecs - 50);
while (sw.ElapsedMilliseconds < millisecs)
;
}
But it is a busy wait and will consume CPU cycles terribly. Also it could be affected by garbage collections or task rescheduling.
Here's the test program:
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Threading;
namespace Demo
{
class Program
{
void run()
{
for (int i = 1; i < 10; ++i)
test(i);
for (int i = 10; i < 100; i += 5)
test(i);
for (int i = 100; i < 200; i += 10)
test(i);
for (int i = 200; i < 500; i += 20)
test(i);
}
void test(int millisecs)
{
var sw = Stopwatch.StartNew();
accurateWait(millisecs);
Console.WriteLine("Requested wait = " + millisecs + ", actual wait = " + sw.ElapsedMilliseconds);
}
void accurateWait(int millisecs)
{
var sw = Stopwatch.StartNew();
if (millisecs >= 100)
Thread.Sleep(millisecs - 50);
while (sw.ElapsedMilliseconds < millisecs)
;
}
static void Main()
{
new Program().run();
}
}
}

Multithreading with Java / Benchmarking against Mono

I'm working on a simple benchmark testing out both Mono's ParallelFX against Java on several Linux boxes. The test for .NET runs great on Windows and Linux alike, but I'm having some kind of snag with the Java version...
I can see the specified number of threads starting up, but they run in a strange fashion. It acts like they start up, but they finish very slowly. They continue to start, but take forever to finish. It seems like it should be exceeding the limit of the thread pool, and my CPU usage looks to me like it's only using one or two cores (I've got an i7 processor so something like 8 should try to be used).
Yes, I know I am not being "thread safe" with my integers and probably other stuff too. I don't really care right now. Something larger is an issue here.
C# Version
public class Program
{
static void Main(string[] args)
{
const int numberOfCycles = 1000;
const int numbersPerCycle = 1000000;
Stopwatch swG = Stopwatch.StartNew();
int threadCount = 0;
int completeCount = 0;
Parallel.For(0, numberOfCycles, x =>
{
Console.WriteLine(string.Format("Starting cycle {0}. Thread count at {1}", x, threadCount++));
Random r = new Random();
Stopwatch sw = Stopwatch.StartNew();
List<double> numbers = new List<double>();
for (int i = 0; i < numbersPerCycle; i++)
{
numbers.Add(r.NextDouble() * 1000);
}
numbers.Sort();
double min = numbers.Min();
double max = numbers.Max();
completeCount++;
Console.WriteLine(string.Format("{0} cycles complete: {1:#,##0.0} ms. Min: {2:0.###} Max: {3:0.###}", completeCount, sw.ElapsedMilliseconds, min, max));
threadCount--;
});
Console.WriteLine(string.Format("All {0} cycles complete. Took {1:#,##0.0} ms.", numberOfCycles, swG.ElapsedMilliseconds));
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
}
Java Version
P.S. I am lazy and stole the Stopwatch class from here: Is there a stopwatch in Java?
public class JavaMonoTest {
static int threadCount = 0;
static int completeCount = 0;
static String CLRF = "\r\n";
public static void main(String[] args) throws IOException, InterruptedException {
final int numberOfCycles = 1000;
final int numbersPerCycle = 1000000;
final int NUM_CORES = Runtime.getRuntime().availableProcessors();
//Setup the running array
List<Integer> cyclesList = new LinkedList<Integer>();
for(int i = 0; i < numberOfCycles; i++){
cyclesList.add(i);
}
Stopwatch swG = new Stopwatch();
swG.start();
ExecutorService exec = Executors.newFixedThreadPool(NUM_CORES);
try {
for (final Integer x : cyclesList) {
exec.submit(new Runnable() {
#Override
public void run() {
System.out.printf("Starting cycle %s. Thread count at %s %s", x, threadCount++, CLRF);
Random r = new Random();
Stopwatch sw = new Stopwatch();
sw.start();
List<Double> numbers = new LinkedList<Double>();
for (int i = 0; i < numbersPerCycle; i++)
{
numbers.add(r.nextDouble() * 1000);
}
Collections.sort(numbers);
double min = Collections.min(numbers);
double max = Collections.max(numbers);
completeCount++;
System.out.printf("%s cycles complete: %.2f ms. Min: %.2f Max: %.2f %s", completeCount, sw.getElapsedTime(), min, max, CLRF);
threadCount--;
}
});
}
} finally {
exec.shutdown();
}
exec.awaitTermination(1, TimeUnit.DAYS);
System.out.printf("All %s cycles complete. Took %.2f ms. %s", numberOfCycles, swG.getElapsedTime(), CLRF);
System.out.println("Press any key to continue.");
System.in.read();
}
}
Updated C# Version to Match Java Version In Answer
public class Program
{
static void Main(string[] args)
{
const int numberOfCycles = 1000;
const int numbersPerCycle = 1000000;
Stopwatch swG = Stopwatch.StartNew();
int threadCount = 0;
int completeCount = 0;
Parallel.For(0, numberOfCycles, x =>
{
Console.WriteLine(string.Format("Starting cycle {0}. Thread count at {1}", x, Interlocked.Increment(ref threadCount)));
Random r = new Random();
Stopwatch sw = Stopwatch.StartNew();
double[] numbers = new double[numbersPerCycle];
for (int i = 0; i < numbersPerCycle; i++)
{
numbers[i] = r.NextDouble() * 1000;
}
Array.Sort(numbers);
double min = numbers[0];
double max = numbers[numbers.Length - 1];
Interlocked.Increment(ref completeCount);
Console.WriteLine(string.Format("{0} cycles complete: {1:#,##0.0} ms. Min: {2:0.###} Max: {3:0.###}", completeCount, sw.ElapsedMilliseconds, min, max));
Interlocked.Decrement(ref threadCount);
});
Console.WriteLine(string.Format("All {0} cycles complete. Took {1:#,##0.0} ms.", numberOfCycles, swG.ElapsedMilliseconds));
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
}
Running the program I see that its using 97%-98% of eight cpus, but also creating an insane amount of garbage. If I make the program more efficient it runs to completion much faster.
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class JavaMonoTest {
static final AtomicInteger threadCount = new AtomicInteger();
static final AtomicInteger completeCount = new AtomicInteger();
public static void main(String[] args) throws InterruptedException {
final int numberOfCycles = 1000;
final int numbersPerCycle = 1000000;
final int NUM_CORES = Runtime.getRuntime().availableProcessors();
long swG = System.nanoTime();
ExecutorService exec = Executors.newFixedThreadPool(NUM_CORES);
try {
for (int i = 0; i < numberOfCycles; i++) {
final int x = i;
exec.submit(new Runnable() {
#Override
public void run() {
try {
System.out.printf("Starting cycle %s. Thread count at %s %n", x, threadCount.getAndIncrement());
Random r = new Random();
long sw = System.nanoTime();
double[] numbers = new double[numbersPerCycle];
for (int i = 0; i < numbersPerCycle; i++) {
numbers[i] = r.nextDouble() * 1000;
}
Arrays.sort(numbers);
double min = numbers[0];
double max = numbers[numbers.length - 1];
completeCount.getAndIncrement();
System.out.printf("%s cycles complete: %.2f ms. Min: %.2f Max: %.2f %n",
completeCount, (System.nanoTime() - sw) / 1e6, min, max);
threadCount.getAndDecrement();
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
} finally {
exec.shutdown();
}
exec.awaitTermination(1, TimeUnit.DAYS);
System.out.printf("All %s cycles complete. Took %.2f ms. %n",
numberOfCycles, (System.nanoTime() - swG) / 1e6);
}
}
prints
Starting cycle 0. Thread count at 0
Starting cycle 7. Thread count at 7
Starting cycle 6. Thread count at 6
... deleted ...
999 cycles complete: 139.28 ms. Min: 0.00 Max: 1000.00
1000 cycles complete: 139.05 ms. Min: 0.00 Max: 1000.00
All 1000 cycles complete. Took 19431.14 ms.
In place of:
ExecutorService exec = Executors.newFixedThreadPool(NUM_CORES);
try {
for (final Integer x : cyclesList) {
exec.submit(new Runnable() {
try:
ExecutorService exec = Executors.newFixedThreadPool(NUM_CORES);
try {
for (final Integer x : cyclesList) {
exec.execute( new Runnable() { // No Future< T > needed

Categories

Resources