In my spare time I decided to write a program that would systematically identify prime numbers from 2 to 18,446,744,073,709,551,615. This is for fun and learning, as I know it will take too long to actually ever reach the upward value, but I'm using this to explore parallel processing. I know this is not a traditional question but I very much would like the critique of my peers. I know this can been torn apart, so please do, but if you do, do so constructively.
The program is designed to run until the user hits the esc key; at which time it will generate a file with all of the prime numbers discovered. The path to this file needs to be configured to a value for your directory structure. When I restart the program it will accept, as an argument, a primes text file, reading it in and starting from where it left off. The parallel processing portion and implementing the sieve for finding primes is what I was interested in woodshedding.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;
namespace Prime
{
public class Program
{
public static void Main(string[] args)
{
List<UInt64> primes = new List<UInt64>();
primes.Add(2);
UInt64 numberToCheck = 3;
if (args.Count() > 0)
{
numberToCheck = ReadPrimesToList(args[0].ToString(), out primes) +2;
}
try
{
bool quit = false;
Console.WriteLine("Prime Number Search");
while (!quit)
{
if (Console.KeyAvailable)
quit = Console.ReadKey().Key == ConsoleKey.Escape;
Console.Write("Processing: " + numberToCheck);
if (CheckForPrime(numberToCheck, primes))
{
primes.Add(numberToCheck);
Console.WriteLine(" Prime Found!");
}
else
Console.WriteLine(" Not Prime :(");
if (numberToCheck < UInt64.MaxValue)
numberToCheck+=2;
else
break;
}
Console.WriteLine("Exiting");
WritePrimesToFile(primes);
Console.WriteLine("< Press Any Key To Exit >");
Console.ReadKey();
}
catch
{
if (primes.Count > 0)
WritePrimesToFile(primes);
}
}
private static UInt64 ReadPrimesToList(string fileName, out List<UInt64> primes)
{
primes = new List<UInt64>();
FileInfo file = new FileInfo(fileName);
StreamReader reader = new StreamReader(file.OpenRead());
String lineIn = String.Empty;
while (!reader.EndOfStream)
{
lineIn = reader.ReadLine();
String[] numberStrings = lineIn.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
foreach (String numberString in numberStrings)
{
primes.Add(UInt64.Parse(numberString));
}
}
return primes[primes.Count() - 1];
}
private static void WritePrimesToFile(List<UInt64> primes)
{
String dateAndTime = DateTime.Now.ToString("yyyyMMddhhmm");
String fileName = String.Format(@"<substitute your path here>\primes [{0}].txt", dateAndTime);
FileInfo file = new FileInfo(fileName);
using (StreamWriter writer = file.CreateText())
{
int maxLength = primes[primes.Count - 1].ToString().Length;
String line = String.Empty;
const int maxColumn = 16;
int column = 0;
foreach (UInt64 number in primes)
{
string numberString = number.ToString();
int numberLength = numberString.Length;
line += numberString.PadLeft(maxLength, ' ') + ((column < (maxColumn-1)) ? " " : String.Empty);
column++;
if (column == maxColumn)
{
writer.WriteLine(line);
line = string.Empty;
column = 0;
}
}
if (line.Length > 0)
writer.WriteLine(line);
writer.Flush();
writer.Close();
}
}
private static bool CheckForPrime(UInt64 numberToCheck, List<UInt64> primes)
{
if ((numberToCheck % 2) == 0)
return false;
UInt64 halfway = (UInt64)(Math.Ceiling((float)numberToCheck / 2F));
bool isprime = false;
UInt64 factor = 0;
Parallel.ForEach<UInt64>(primes, (prime, loopState) =>
{
if (prime > halfway)
{
isprime = true;
loopState.Stop();
}
if ((numberToCheck % prime) == 0)
{
factor = prime;
isprime = false;
loopState.Stop();
}
});
return (isprime && factor == 0);
}
}
}