patterncsharpMinor
Finding and testing primality
Viewed 0 times
andtestingprimalityfinding
Problem
I have written a class who is responsible for both enumerating primes and testing the primality of a number.
Here is the code :
```
public static class Primes
{
private static ulong g_MaxTested;
private static ulong g_MaxFound;
private static readonly HashSet g_KnownPrimes;
static Primes()
{
// All primes below 1000 (http://en.wikipedia.org/wiki/Primes)
g_KnownPrimes = new HashSet() {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73,
79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251,
257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557,
563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647,
653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757,
761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983,
991, 997
};
g_MaxTested = 997;
g_MaxFound = 997;
}
private static void EnsureExploredUpTo(ulong upperBound)
{
if (upperBound x value % x == 0);
}
public static bool IsPrime(ulong value)
{
if (value == 1) return false;
EnsureExploredUpTo(value);
return g_KnownPrimes.Contains(value);
}
public static IEnumerable GetPrimes(ulong upperBound = ulong.MaxValue)
{
// First return all known primes :
foreach (var prime in g_KnownPrimes)
{
if (prime > upperBound) yield break;
yield return
Here is the code :
```
public static class Primes
{
private static ulong g_MaxTested;
private static ulong g_MaxFound;
private static readonly HashSet g_KnownPrimes;
static Primes()
{
// All primes below 1000 (http://en.wikipedia.org/wiki/Primes)
g_KnownPrimes = new HashSet() {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73,
79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251,
257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557,
563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647,
653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757,
761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983,
991, 997
};
g_MaxTested = 997;
g_MaxFound = 997;
}
private static void EnsureExploredUpTo(ulong upperBound)
{
if (upperBound x value % x == 0);
}
public static bool IsPrime(ulong value)
{
if (value == 1) return false;
EnsureExploredUpTo(value);
return g_KnownPrimes.Contains(value);
}
public static IEnumerable GetPrimes(ulong upperBound = ulong.MaxValue)
{
// First return all known primes :
foreach (var prime in g_KnownPrimes)
{
if (prime > upperBound) yield break;
yield return
Solution
This is a valid sieve but the HashSet MAY not be as fast as an Array or ArrayList. These will preserve the order of the elements, so you could implement a quick membership check with a binary search. They would likely be faster to iterate over in general -- they should especially speed up iteration for testing the primality of a sequence of odd numbers. In 33% of the cases, the testing would not get past
BTW, testing odd numbers for
But you should definitely benchmark either of these suggestions on a mix of input sequences with typical numbers of input values, maximum input values, and tendencies to raise the high water value early vs. late in the sequence.
One last note:
x % 3. Doing these tests in HashSet order wastes lots of time checking against higher primes in the HashSet that rarely change the outcome. Listing primes in a HashSet order that may change as the set of primes grows seems slightly less useful than listing in increasing order.BTW, testing odd numbers for
x % 2 is a waste of time, especially if that's going to be the first test -- you might want to consider pulling 2 out of your primes list and handling it separately only when you have to.But you should definitely benchmark either of these suggestions on a mix of input sequences with typical numbers of input values, maximum input values, and tendencies to raise the high water value early vs. late in the sequence.
One last note:
g_MaxFound doesn't cost much and is nice for diagnostic purposes, but it's not actually used in the implementation. I usually mark non-critical variables like this with special names or at least comments to avoid confusion with the operational values.Context
StackExchange Code Review Q#8585, answer score: 3
Revisions (0)
No revisions yet.