Prime engine: generation, primality, factorization
up vote
2
down vote
favorite
I've just written my first C# class, so I'm looking for some feedback before I go and write more code. The goal of the code is to provide a Singleton-like class to deal with common operations on the set of prime numbers that I will need to complete projecteuler.net problems.
I'm interested in feedback for all aspects of the implementation (short of the actual prime generation algorithms, the 6*i +/- 1
method was used solely for its simplicity).
I'm also interested in feedback about how the interfaces are split up. I split these up into slices of functionality in an attempt to allow future implementation changes. I am planning to use DI (e.g. SimpleInjector) to bind the singleton instance to each of the interfaces, but I'm seriously starting to doubt this pattern.
I'm less interested in feedback about the selections of methods, I just chose a relatively minimal subset of methods that I know that I will need at some point - more methods will probably be added as needed.
Interfaces
public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}
public interface IPrimeChecker
{
bool IsPrime(long value);
}
public interface IPrimeFactorizer
{
IEnumerable<long> PrimeFactors(long value);
IEnumerable<long> UniquePrimeFactors(long value);
}
Implementation
public class PrimeEngine: IPrimeGenerator, IPrimeChecker, IPrimeFactorizer
{
private readonly ICollection<long> _primeCollection;
private long _indexFactor;
private long _maxChecked;
public PrimeEngine()
{
_primeCollection = new Collection<long> {2, 3};
_indexFactor = 1;
_maxChecked = 3;
}
private void CheckNextPossiblePrimeDoublet()
{
var low = 6 * _indexFactor - 1;
var high = low + 2;
if (IsPrime(low))
{
_primeCollection.Add(low);
}
if (IsPrime(high))
{
_primeCollection.Add(high);
}
_indexFactor += 1;
_maxChecked = high;
}
private IEnumerable<long> GetPossibleSmallerPrimeFactors(long value)
{
FillPrimesUntilRoot(value);
return PrimesUntilRoot(value);
}
public bool IsPrime(long value)
{
var primePool = GetPossibleSmallerPrimeFactors(value);
return primePool.All(prime => value % prime != 0);
}
private void FillPrimesUntilValue(long value)
{
while (_maxChecked < value)
{
CheckNextPossiblePrimeDoublet();
}
}
private void FillPrimesUntilCount(int count)
{
while (_primeCollection.Count < count)
{
CheckNextPossiblePrimeDoublet();
}
}
private static long FloorOfRoot(long value)
{
return (long) Math.Floor(Math.Sqrt(value));
}
private void FillPrimesUntilRoot(long value)
{
FillPrimesUntilValue(FloorOfRoot(value));
}
public IEnumerable<long> PrimesUntilValue(long value)
{
FillPrimesUntilValue(value);
return _primeCollection.TakeWhile(prime => prime <= value);
}
public IEnumerable<long> PrimesUntilCount(int count)
{
FillPrimesUntilCount(count);
return _primeCollection.Take(count);
}
public IEnumerable<long> PrimesUntilRoot(long value)
{
return PrimesUntilValue(FloorOfRoot(value));
}
public IEnumerable<long> PrimeFactors(long value)
{
FillPrimesUntilRoot(value);
foreach (var prime in PrimesUntilRoot(value))
{
if (prime > value) break;
while (value % prime == 0)
{
yield return prime;
value /= prime;
}
}
if (value != 1)
{
yield return value;
}
}
public IEnumerable<long> UniquePrimeFactors(long value)
{
return PrimeFactors(value).Distinct();
}
}
c# beginner primes
add a comment |
up vote
2
down vote
favorite
I've just written my first C# class, so I'm looking for some feedback before I go and write more code. The goal of the code is to provide a Singleton-like class to deal with common operations on the set of prime numbers that I will need to complete projecteuler.net problems.
I'm interested in feedback for all aspects of the implementation (short of the actual prime generation algorithms, the 6*i +/- 1
method was used solely for its simplicity).
I'm also interested in feedback about how the interfaces are split up. I split these up into slices of functionality in an attempt to allow future implementation changes. I am planning to use DI (e.g. SimpleInjector) to bind the singleton instance to each of the interfaces, but I'm seriously starting to doubt this pattern.
I'm less interested in feedback about the selections of methods, I just chose a relatively minimal subset of methods that I know that I will need at some point - more methods will probably be added as needed.
Interfaces
public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}
public interface IPrimeChecker
{
bool IsPrime(long value);
}
public interface IPrimeFactorizer
{
IEnumerable<long> PrimeFactors(long value);
IEnumerable<long> UniquePrimeFactors(long value);
}
Implementation
public class PrimeEngine: IPrimeGenerator, IPrimeChecker, IPrimeFactorizer
{
private readonly ICollection<long> _primeCollection;
private long _indexFactor;
private long _maxChecked;
public PrimeEngine()
{
_primeCollection = new Collection<long> {2, 3};
_indexFactor = 1;
_maxChecked = 3;
}
private void CheckNextPossiblePrimeDoublet()
{
var low = 6 * _indexFactor - 1;
var high = low + 2;
if (IsPrime(low))
{
_primeCollection.Add(low);
}
if (IsPrime(high))
{
_primeCollection.Add(high);
}
_indexFactor += 1;
_maxChecked = high;
}
private IEnumerable<long> GetPossibleSmallerPrimeFactors(long value)
{
FillPrimesUntilRoot(value);
return PrimesUntilRoot(value);
}
public bool IsPrime(long value)
{
var primePool = GetPossibleSmallerPrimeFactors(value);
return primePool.All(prime => value % prime != 0);
}
private void FillPrimesUntilValue(long value)
{
while (_maxChecked < value)
{
CheckNextPossiblePrimeDoublet();
}
}
private void FillPrimesUntilCount(int count)
{
while (_primeCollection.Count < count)
{
CheckNextPossiblePrimeDoublet();
}
}
private static long FloorOfRoot(long value)
{
return (long) Math.Floor(Math.Sqrt(value));
}
private void FillPrimesUntilRoot(long value)
{
FillPrimesUntilValue(FloorOfRoot(value));
}
public IEnumerable<long> PrimesUntilValue(long value)
{
FillPrimesUntilValue(value);
return _primeCollection.TakeWhile(prime => prime <= value);
}
public IEnumerable<long> PrimesUntilCount(int count)
{
FillPrimesUntilCount(count);
return _primeCollection.Take(count);
}
public IEnumerable<long> PrimesUntilRoot(long value)
{
return PrimesUntilValue(FloorOfRoot(value));
}
public IEnumerable<long> PrimeFactors(long value)
{
FillPrimesUntilRoot(value);
foreach (var prime in PrimesUntilRoot(value))
{
if (prime > value) break;
while (value % prime == 0)
{
yield return prime;
value /= prime;
}
}
if (value != 1)
{
yield return value;
}
}
public IEnumerable<long> UniquePrimeFactors(long value)
{
return PrimeFactors(value).Distinct();
}
}
c# beginner primes
2
The two first interfaces are identical - a copy/paste mistake?
– t3chb0t
Nov 26 at 7:14
@t3 Nice catch, thanks!
– Jared Goguen
Nov 26 at 14:00
In many applications of prime numbers aNextPrime(int value)
method, returning the next higher prime can be useful. Hint: after 2 and 3, all prime numbers are of the form 6n ± 1.
– rossum
Nov 28 at 15:01
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I've just written my first C# class, so I'm looking for some feedback before I go and write more code. The goal of the code is to provide a Singleton-like class to deal with common operations on the set of prime numbers that I will need to complete projecteuler.net problems.
I'm interested in feedback for all aspects of the implementation (short of the actual prime generation algorithms, the 6*i +/- 1
method was used solely for its simplicity).
I'm also interested in feedback about how the interfaces are split up. I split these up into slices of functionality in an attempt to allow future implementation changes. I am planning to use DI (e.g. SimpleInjector) to bind the singleton instance to each of the interfaces, but I'm seriously starting to doubt this pattern.
I'm less interested in feedback about the selections of methods, I just chose a relatively minimal subset of methods that I know that I will need at some point - more methods will probably be added as needed.
Interfaces
public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}
public interface IPrimeChecker
{
bool IsPrime(long value);
}
public interface IPrimeFactorizer
{
IEnumerable<long> PrimeFactors(long value);
IEnumerable<long> UniquePrimeFactors(long value);
}
Implementation
public class PrimeEngine: IPrimeGenerator, IPrimeChecker, IPrimeFactorizer
{
private readonly ICollection<long> _primeCollection;
private long _indexFactor;
private long _maxChecked;
public PrimeEngine()
{
_primeCollection = new Collection<long> {2, 3};
_indexFactor = 1;
_maxChecked = 3;
}
private void CheckNextPossiblePrimeDoublet()
{
var low = 6 * _indexFactor - 1;
var high = low + 2;
if (IsPrime(low))
{
_primeCollection.Add(low);
}
if (IsPrime(high))
{
_primeCollection.Add(high);
}
_indexFactor += 1;
_maxChecked = high;
}
private IEnumerable<long> GetPossibleSmallerPrimeFactors(long value)
{
FillPrimesUntilRoot(value);
return PrimesUntilRoot(value);
}
public bool IsPrime(long value)
{
var primePool = GetPossibleSmallerPrimeFactors(value);
return primePool.All(prime => value % prime != 0);
}
private void FillPrimesUntilValue(long value)
{
while (_maxChecked < value)
{
CheckNextPossiblePrimeDoublet();
}
}
private void FillPrimesUntilCount(int count)
{
while (_primeCollection.Count < count)
{
CheckNextPossiblePrimeDoublet();
}
}
private static long FloorOfRoot(long value)
{
return (long) Math.Floor(Math.Sqrt(value));
}
private void FillPrimesUntilRoot(long value)
{
FillPrimesUntilValue(FloorOfRoot(value));
}
public IEnumerable<long> PrimesUntilValue(long value)
{
FillPrimesUntilValue(value);
return _primeCollection.TakeWhile(prime => prime <= value);
}
public IEnumerable<long> PrimesUntilCount(int count)
{
FillPrimesUntilCount(count);
return _primeCollection.Take(count);
}
public IEnumerable<long> PrimesUntilRoot(long value)
{
return PrimesUntilValue(FloorOfRoot(value));
}
public IEnumerable<long> PrimeFactors(long value)
{
FillPrimesUntilRoot(value);
foreach (var prime in PrimesUntilRoot(value))
{
if (prime > value) break;
while (value % prime == 0)
{
yield return prime;
value /= prime;
}
}
if (value != 1)
{
yield return value;
}
}
public IEnumerable<long> UniquePrimeFactors(long value)
{
return PrimeFactors(value).Distinct();
}
}
c# beginner primes
I've just written my first C# class, so I'm looking for some feedback before I go and write more code. The goal of the code is to provide a Singleton-like class to deal with common operations on the set of prime numbers that I will need to complete projecteuler.net problems.
I'm interested in feedback for all aspects of the implementation (short of the actual prime generation algorithms, the 6*i +/- 1
method was used solely for its simplicity).
I'm also interested in feedback about how the interfaces are split up. I split these up into slices of functionality in an attempt to allow future implementation changes. I am planning to use DI (e.g. SimpleInjector) to bind the singleton instance to each of the interfaces, but I'm seriously starting to doubt this pattern.
I'm less interested in feedback about the selections of methods, I just chose a relatively minimal subset of methods that I know that I will need at some point - more methods will probably be added as needed.
Interfaces
public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}
public interface IPrimeChecker
{
bool IsPrime(long value);
}
public interface IPrimeFactorizer
{
IEnumerable<long> PrimeFactors(long value);
IEnumerable<long> UniquePrimeFactors(long value);
}
Implementation
public class PrimeEngine: IPrimeGenerator, IPrimeChecker, IPrimeFactorizer
{
private readonly ICollection<long> _primeCollection;
private long _indexFactor;
private long _maxChecked;
public PrimeEngine()
{
_primeCollection = new Collection<long> {2, 3};
_indexFactor = 1;
_maxChecked = 3;
}
private void CheckNextPossiblePrimeDoublet()
{
var low = 6 * _indexFactor - 1;
var high = low + 2;
if (IsPrime(low))
{
_primeCollection.Add(low);
}
if (IsPrime(high))
{
_primeCollection.Add(high);
}
_indexFactor += 1;
_maxChecked = high;
}
private IEnumerable<long> GetPossibleSmallerPrimeFactors(long value)
{
FillPrimesUntilRoot(value);
return PrimesUntilRoot(value);
}
public bool IsPrime(long value)
{
var primePool = GetPossibleSmallerPrimeFactors(value);
return primePool.All(prime => value % prime != 0);
}
private void FillPrimesUntilValue(long value)
{
while (_maxChecked < value)
{
CheckNextPossiblePrimeDoublet();
}
}
private void FillPrimesUntilCount(int count)
{
while (_primeCollection.Count < count)
{
CheckNextPossiblePrimeDoublet();
}
}
private static long FloorOfRoot(long value)
{
return (long) Math.Floor(Math.Sqrt(value));
}
private void FillPrimesUntilRoot(long value)
{
FillPrimesUntilValue(FloorOfRoot(value));
}
public IEnumerable<long> PrimesUntilValue(long value)
{
FillPrimesUntilValue(value);
return _primeCollection.TakeWhile(prime => prime <= value);
}
public IEnumerable<long> PrimesUntilCount(int count)
{
FillPrimesUntilCount(count);
return _primeCollection.Take(count);
}
public IEnumerable<long> PrimesUntilRoot(long value)
{
return PrimesUntilValue(FloorOfRoot(value));
}
public IEnumerable<long> PrimeFactors(long value)
{
FillPrimesUntilRoot(value);
foreach (var prime in PrimesUntilRoot(value))
{
if (prime > value) break;
while (value % prime == 0)
{
yield return prime;
value /= prime;
}
}
if (value != 1)
{
yield return value;
}
}
public IEnumerable<long> UniquePrimeFactors(long value)
{
return PrimeFactors(value).Distinct();
}
}
c# beginner primes
c# beginner primes
edited Nov 26 at 13:59
Maxime Recuerda
1943
1943
asked Nov 26 at 3:16
Jared Goguen
787313
787313
2
The two first interfaces are identical - a copy/paste mistake?
– t3chb0t
Nov 26 at 7:14
@t3 Nice catch, thanks!
– Jared Goguen
Nov 26 at 14:00
In many applications of prime numbers aNextPrime(int value)
method, returning the next higher prime can be useful. Hint: after 2 and 3, all prime numbers are of the form 6n ± 1.
– rossum
Nov 28 at 15:01
add a comment |
2
The two first interfaces are identical - a copy/paste mistake?
– t3chb0t
Nov 26 at 7:14
@t3 Nice catch, thanks!
– Jared Goguen
Nov 26 at 14:00
In many applications of prime numbers aNextPrime(int value)
method, returning the next higher prime can be useful. Hint: after 2 and 3, all prime numbers are of the form 6n ± 1.
– rossum
Nov 28 at 15:01
2
2
The two first interfaces are identical - a copy/paste mistake?
– t3chb0t
Nov 26 at 7:14
The two first interfaces are identical - a copy/paste mistake?
– t3chb0t
Nov 26 at 7:14
@t3 Nice catch, thanks!
– Jared Goguen
Nov 26 at 14:00
@t3 Nice catch, thanks!
– Jared Goguen
Nov 26 at 14:00
In many applications of prime numbers a
NextPrime(int value)
method, returning the next higher prime can be useful. Hint: after 2 and 3, all prime numbers are of the form 6n ± 1.– rossum
Nov 28 at 15:01
In many applications of prime numbers a
NextPrime(int value)
method, returning the next higher prime can be useful. Hint: after 2 and 3, all prime numbers are of the form 6n ± 1.– rossum
Nov 28 at 15:01
add a comment |
2 Answers
2
active
oldest
votes
up vote
2
down vote
This is excellent code for a beginner. It's neat, the methods are short, etc. However, there are a couple things I'm concerned with.
1) Your engine has a lot of state. It looks like this is mostly related to the generation of the next prime sequences, and any found primes are cached, so it shouldn't be too bad. However, you have to test that calling PrimesUntilValue
followed by UniquePrimeFactors
, for example, doesn't generate "duplicate" values or skip any.
2) Given that you are using an approximation for primes, your code is structured neatly. However, do note that actually generating the sequence might get a bit messier than this and don't expect to be able to swap it out neatly. Given that your class's state is solely used for generating the next prime and that all previously found values are cached, it shouldn't be an issue.
3) This code could lead to massive memory use in an application. Since you are already caching the values and all, you should consider making it a static
class and making the cached collection a thread-safe hashmap. Then you have one instance of the prime engine and can do things like PrimeEngine.PrimesUntilRoot
, etc. The hashmap would prevent duplicate primes from being entered into the collection.
add a comment |
up vote
2
down vote
I agree with @Hosch250 ... too much state in what really could be self-contained static methods. I am struggling to see why you would want any of the class-level variables.
I personally do not like the interfaces, mainly because you can define it only to 1 integer type (long or Int64). Why not Int32, UInt32, or even UInt64? Granted Int32 gets a free ride with the Int64 version.
For some functions, there is way too much bloat in terms of memory and time. If you want to check that a number is prime, why bother checking for its entire prime factors collection? Once you detect that a number is not prime, the IsPrime method should return immediately rather than clicking along to find out if there are other prime factors.
On a positive note, the code is written neatly and is easy to understand.
How would I go about expanding the interfaces to accept variable types?
– Jared Goguen
Nov 26 at 19:46
@JaredGoguen That's just it - you can't, which is why I don't like the interfaces for this solution. Consider something like Math.Max. All the integral types have that method but it can't be tied to an interface because the interface declares one specific output type for a method. To put it another way, if you want an Int32 method to return an Int32, and a similarly named UInt64 method to return an UInt64, they can't be declared by an interface.
– Rick Davin
Nov 28 at 13:30
Generics would work.IPrimeGenerator<T>
– Hosch250
Nov 30 at 17:18
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
This is excellent code for a beginner. It's neat, the methods are short, etc. However, there are a couple things I'm concerned with.
1) Your engine has a lot of state. It looks like this is mostly related to the generation of the next prime sequences, and any found primes are cached, so it shouldn't be too bad. However, you have to test that calling PrimesUntilValue
followed by UniquePrimeFactors
, for example, doesn't generate "duplicate" values or skip any.
2) Given that you are using an approximation for primes, your code is structured neatly. However, do note that actually generating the sequence might get a bit messier than this and don't expect to be able to swap it out neatly. Given that your class's state is solely used for generating the next prime and that all previously found values are cached, it shouldn't be an issue.
3) This code could lead to massive memory use in an application. Since you are already caching the values and all, you should consider making it a static
class and making the cached collection a thread-safe hashmap. Then you have one instance of the prime engine and can do things like PrimeEngine.PrimesUntilRoot
, etc. The hashmap would prevent duplicate primes from being entered into the collection.
add a comment |
up vote
2
down vote
This is excellent code for a beginner. It's neat, the methods are short, etc. However, there are a couple things I'm concerned with.
1) Your engine has a lot of state. It looks like this is mostly related to the generation of the next prime sequences, and any found primes are cached, so it shouldn't be too bad. However, you have to test that calling PrimesUntilValue
followed by UniquePrimeFactors
, for example, doesn't generate "duplicate" values or skip any.
2) Given that you are using an approximation for primes, your code is structured neatly. However, do note that actually generating the sequence might get a bit messier than this and don't expect to be able to swap it out neatly. Given that your class's state is solely used for generating the next prime and that all previously found values are cached, it shouldn't be an issue.
3) This code could lead to massive memory use in an application. Since you are already caching the values and all, you should consider making it a static
class and making the cached collection a thread-safe hashmap. Then you have one instance of the prime engine and can do things like PrimeEngine.PrimesUntilRoot
, etc. The hashmap would prevent duplicate primes from being entered into the collection.
add a comment |
up vote
2
down vote
up vote
2
down vote
This is excellent code for a beginner. It's neat, the methods are short, etc. However, there are a couple things I'm concerned with.
1) Your engine has a lot of state. It looks like this is mostly related to the generation of the next prime sequences, and any found primes are cached, so it shouldn't be too bad. However, you have to test that calling PrimesUntilValue
followed by UniquePrimeFactors
, for example, doesn't generate "duplicate" values or skip any.
2) Given that you are using an approximation for primes, your code is structured neatly. However, do note that actually generating the sequence might get a bit messier than this and don't expect to be able to swap it out neatly. Given that your class's state is solely used for generating the next prime and that all previously found values are cached, it shouldn't be an issue.
3) This code could lead to massive memory use in an application. Since you are already caching the values and all, you should consider making it a static
class and making the cached collection a thread-safe hashmap. Then you have one instance of the prime engine and can do things like PrimeEngine.PrimesUntilRoot
, etc. The hashmap would prevent duplicate primes from being entered into the collection.
This is excellent code for a beginner. It's neat, the methods are short, etc. However, there are a couple things I'm concerned with.
1) Your engine has a lot of state. It looks like this is mostly related to the generation of the next prime sequences, and any found primes are cached, so it shouldn't be too bad. However, you have to test that calling PrimesUntilValue
followed by UniquePrimeFactors
, for example, doesn't generate "duplicate" values or skip any.
2) Given that you are using an approximation for primes, your code is structured neatly. However, do note that actually generating the sequence might get a bit messier than this and don't expect to be able to swap it out neatly. Given that your class's state is solely used for generating the next prime and that all previously found values are cached, it shouldn't be an issue.
3) This code could lead to massive memory use in an application. Since you are already caching the values and all, you should consider making it a static
class and making the cached collection a thread-safe hashmap. Then you have one instance of the prime engine and can do things like PrimeEngine.PrimesUntilRoot
, etc. The hashmap would prevent duplicate primes from being entered into the collection.
answered Nov 26 at 15:44
Hosch250
17.2k564156
17.2k564156
add a comment |
add a comment |
up vote
2
down vote
I agree with @Hosch250 ... too much state in what really could be self-contained static methods. I am struggling to see why you would want any of the class-level variables.
I personally do not like the interfaces, mainly because you can define it only to 1 integer type (long or Int64). Why not Int32, UInt32, or even UInt64? Granted Int32 gets a free ride with the Int64 version.
For some functions, there is way too much bloat in terms of memory and time. If you want to check that a number is prime, why bother checking for its entire prime factors collection? Once you detect that a number is not prime, the IsPrime method should return immediately rather than clicking along to find out if there are other prime factors.
On a positive note, the code is written neatly and is easy to understand.
How would I go about expanding the interfaces to accept variable types?
– Jared Goguen
Nov 26 at 19:46
@JaredGoguen That's just it - you can't, which is why I don't like the interfaces for this solution. Consider something like Math.Max. All the integral types have that method but it can't be tied to an interface because the interface declares one specific output type for a method. To put it another way, if you want an Int32 method to return an Int32, and a similarly named UInt64 method to return an UInt64, they can't be declared by an interface.
– Rick Davin
Nov 28 at 13:30
Generics would work.IPrimeGenerator<T>
– Hosch250
Nov 30 at 17:18
add a comment |
up vote
2
down vote
I agree with @Hosch250 ... too much state in what really could be self-contained static methods. I am struggling to see why you would want any of the class-level variables.
I personally do not like the interfaces, mainly because you can define it only to 1 integer type (long or Int64). Why not Int32, UInt32, or even UInt64? Granted Int32 gets a free ride with the Int64 version.
For some functions, there is way too much bloat in terms of memory and time. If you want to check that a number is prime, why bother checking for its entire prime factors collection? Once you detect that a number is not prime, the IsPrime method should return immediately rather than clicking along to find out if there are other prime factors.
On a positive note, the code is written neatly and is easy to understand.
How would I go about expanding the interfaces to accept variable types?
– Jared Goguen
Nov 26 at 19:46
@JaredGoguen That's just it - you can't, which is why I don't like the interfaces for this solution. Consider something like Math.Max. All the integral types have that method but it can't be tied to an interface because the interface declares one specific output type for a method. To put it another way, if you want an Int32 method to return an Int32, and a similarly named UInt64 method to return an UInt64, they can't be declared by an interface.
– Rick Davin
Nov 28 at 13:30
Generics would work.IPrimeGenerator<T>
– Hosch250
Nov 30 at 17:18
add a comment |
up vote
2
down vote
up vote
2
down vote
I agree with @Hosch250 ... too much state in what really could be self-contained static methods. I am struggling to see why you would want any of the class-level variables.
I personally do not like the interfaces, mainly because you can define it only to 1 integer type (long or Int64). Why not Int32, UInt32, or even UInt64? Granted Int32 gets a free ride with the Int64 version.
For some functions, there is way too much bloat in terms of memory and time. If you want to check that a number is prime, why bother checking for its entire prime factors collection? Once you detect that a number is not prime, the IsPrime method should return immediately rather than clicking along to find out if there are other prime factors.
On a positive note, the code is written neatly and is easy to understand.
I agree with @Hosch250 ... too much state in what really could be self-contained static methods. I am struggling to see why you would want any of the class-level variables.
I personally do not like the interfaces, mainly because you can define it only to 1 integer type (long or Int64). Why not Int32, UInt32, or even UInt64? Granted Int32 gets a free ride with the Int64 version.
For some functions, there is way too much bloat in terms of memory and time. If you want to check that a number is prime, why bother checking for its entire prime factors collection? Once you detect that a number is not prime, the IsPrime method should return immediately rather than clicking along to find out if there are other prime factors.
On a positive note, the code is written neatly and is easy to understand.
answered Nov 26 at 16:06
Rick Davin
3,107718
3,107718
How would I go about expanding the interfaces to accept variable types?
– Jared Goguen
Nov 26 at 19:46
@JaredGoguen That's just it - you can't, which is why I don't like the interfaces for this solution. Consider something like Math.Max. All the integral types have that method but it can't be tied to an interface because the interface declares one specific output type for a method. To put it another way, if you want an Int32 method to return an Int32, and a similarly named UInt64 method to return an UInt64, they can't be declared by an interface.
– Rick Davin
Nov 28 at 13:30
Generics would work.IPrimeGenerator<T>
– Hosch250
Nov 30 at 17:18
add a comment |
How would I go about expanding the interfaces to accept variable types?
– Jared Goguen
Nov 26 at 19:46
@JaredGoguen That's just it - you can't, which is why I don't like the interfaces for this solution. Consider something like Math.Max. All the integral types have that method but it can't be tied to an interface because the interface declares one specific output type for a method. To put it another way, if you want an Int32 method to return an Int32, and a similarly named UInt64 method to return an UInt64, they can't be declared by an interface.
– Rick Davin
Nov 28 at 13:30
Generics would work.IPrimeGenerator<T>
– Hosch250
Nov 30 at 17:18
How would I go about expanding the interfaces to accept variable types?
– Jared Goguen
Nov 26 at 19:46
How would I go about expanding the interfaces to accept variable types?
– Jared Goguen
Nov 26 at 19:46
@JaredGoguen That's just it - you can't, which is why I don't like the interfaces for this solution. Consider something like Math.Max. All the integral types have that method but it can't be tied to an interface because the interface declares one specific output type for a method. To put it another way, if you want an Int32 method to return an Int32, and a similarly named UInt64 method to return an UInt64, they can't be declared by an interface.
– Rick Davin
Nov 28 at 13:30
@JaredGoguen That's just it - you can't, which is why I don't like the interfaces for this solution. Consider something like Math.Max. All the integral types have that method but it can't be tied to an interface because the interface declares one specific output type for a method. To put it another way, if you want an Int32 method to return an Int32, and a similarly named UInt64 method to return an UInt64, they can't be declared by an interface.
– Rick Davin
Nov 28 at 13:30
Generics would work.
IPrimeGenerator<T>
– Hosch250
Nov 30 at 17:18
Generics would work.
IPrimeGenerator<T>
– Hosch250
Nov 30 at 17:18
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208424%2fprime-engine-generation-primality-factorization%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
The two first interfaces are identical - a copy/paste mistake?
– t3chb0t
Nov 26 at 7:14
@t3 Nice catch, thanks!
– Jared Goguen
Nov 26 at 14:00
In many applications of prime numbers a
NextPrime(int value)
method, returning the next higher prime can be useful. Hint: after 2 and 3, all prime numbers are of the form 6n ± 1.– rossum
Nov 28 at 15:01