I'm trying to generate prime numbers based on user input. This is what I have so far but I just can't seem to figure it out:
Console.Write("Please enter the number of prime numbers you would like to see:");
int numberOfPrimes = Convert.ToInt32(Console.ReadLine());
for (int x = 0; x < numberOfPrimes; x++)
{
for (int a = 2; a <= x ; ++a)
{
bool prime = true;
for (int b = 2; b < a; ++b)
{
if (a % b == 0)
{
prime = false;
}//end if
}//end double nested for
if (prime == true)
{
Console.WriteLine(a);
}//end if
}//end nested for
}//end for
You should be able to see why your results are wrong quite easily if you look at your loop structures. Step through them by hand (it won't take long).
The reason that you are getting your current results is that not every iteration of the outer loop (x < numberOfPrimes) produces a result - it will skip quite a few iterations due to the way the inner loop is structured.
What you really need to do is restructure the inner loops. Your innermost loop works fine, and should detect any prime numbers. Your second loop, however, should only test numbers that haven't yet been tested. Also, it should stop looping once you find a prime number.
You should structure your code better, it's really messy the way you do it now. Have a method IsPrime(int x) which returns true if x is prime and false otherwise.
Then, to generate numberOfPrimes primes, you can do something like this:
for ( int primeCount = 0, currentPrime = 2; primeCount < numberOfPrimes; ++currentPrime )
if ( IsPrime(currentPrime) )
{
// do whatever you want with currentPrime, like print it
++primeCount;
}
Or use the Sieve of Eratosthenes, which is a much faster method.
To figure out if a number x is prime or not, try all of its factors between 2 and Sqrt(x). Why only Sqrt(x)? Because if a*b = x, then x / b = a and x / a = b, So you would check everything twice, and also check things you shouldn't if you went up to x / 2 or even x.
So something like this if you want to use the IsPrime(x) function:
// i <= Sqrt(x) <=> i * i <= x
for ( int i = 2; i * i <= x; ++i )
if ( x % i == 0 )
return false;
return true;
But I suggest you use the sieve of Eratosthenes, as it's much faster. You can also optimize things so you don't check even numbers, since an even number is never prime, except for 2 (both in the sieve and the naive method). Treat x = 2 as an edge case and then start checking every other number (3, 5, 7, 9, 11 etc.)
What you are looking for is called "Sieve of Eratosthenes." As I'm not into doing people's homework, this is the only clue I'm going to give you. The algorithm is easily found on the internet.
The next prime number (x) - is the number which cant be devided by all primes s, that s<=sqrt(x).
So you can use function like
public bool CheckAndAddPrime(int number,List<int> primes)
{
var sqrt = Math.Sqrt(number);
foreach(var prime in primes)
{
if(prime>sqrt) break;
if(number % prime == 0) return false;
}
primes.Add(number);
return true;
}
And than you can get primes like
var primes = new List<int>();
Enumerable.Range(2,int.MaxValue).Where(x => x.CheckAndAddPrime(x,primes)).Take(YouCountOfPrimes);
var primes = Enumerable.Range(1, numberOfPrimes )
.Where(x => x != 1 &&
!Enumerable.Range2, (int)Math.Sqrt(x)).Any(y => x != y && x % y == 0));
copied from codethinked.com
static void Main(string[] args)
{
foreach (int no in get_first_k_primes(10))
{
Console.Write(" "+no.ToString() );
}
}
public static List<int> get_first_k_primes(int k)
{
var primes = new List<int>();
primes.Add(2);
int i = 3;
while(primes.Count < k)
{
if(is_prime(i))
primes.Add(i);
i += 2;
}
return primes;
}
public static bool is_prime(int n)
{
if (n % 2 == 0 && n != 2) return false;
int m = (int)Math.Ceiling(Math.Sqrt(n));
for (int i = 3; i < m; i += 2)
{
if (n % i == 0) return false;
}
return true;
}
1. Rename your variables.
Firstly, if this is homework you will get bad marks (if your teacher is worth his salt) because you have meaningless variable names (yes, even numberOfPrimes is wrong and should be named requiredNumberOfPrimes. When I see this variable I am asking myself 'Is this how many he wants, or how many he has found?').
Secondly, it will help you understand where you are going wrong. Variables should be logically named according to what they represent. If you can't explain what your variables represent (e.g. a & b) then you probably can't explain what you are doing with them.
2. Look at your loops.
for (int x = 0; x < numberOfPrimes; x++)
The structure of a for loop is (initialise; 'should I continue?'; 'each loop do this'). Therefore in your loop
You are continuing until x is equal to or great than numberOfPrimes*.
Each time you go through the loop you are adding 1 to x.
Are you sure this is what you want to do? x appears to represent the number of primes you have found. So why not increment it when you find a prime, rather than when you start a loop?
for (int a = 2; a <= x ; ++a)
for (int b = 2; b < a; ++b)
You are looking at each integer between 2 and x, inclusive. And for each of those integers a, you are looking at every integer between a and 2 inclusive. What are you going to do with these integers?
Every time you loop through your top-level loop (the x loop), you are going to start your a loop from scratch, and every time you loop through your a loop you will start your b loop from scratch.
So if x is 10, you run through a once (a=2), then you run through a again (a=2, a=3), then you run through a again (a=2, a=3, a=4), then...
3. Collect your results rather than writing them to Console.
var primes = new List<int>();
It's so easy. When you find a prime, primes.Add(a);. Then you know how many primes you have found (primes.Count), you can use the list of primes to efficiently determine the next prime, and you can use the list later on if required.
Once you do get ithe loops sorted out, you only have to check for b < sqrt(a), any higher and you would have found the other factor first.
Related
I am trying to calculate the number of combinations of the number of elements in a certain array. I need the exact number of combinations to use it as number of threads to be executed in the GPU.
But the data is very big and the factorial can't be calculated for that big a number with any data type.
Is there a way to calculate the number of combinations without having to find the factorial? Or a more efficient way to do so?
It summarizes the problem:
int no_of_combinations = combination(500,2);
public static int factorial(int m)
{
int x = 1;
for (int i = m; i > 0; i--)
x = x * i;
return x;
}
public static int combination(int m, int n)
{
int x = 0;
x = factorial(m) / (factorial(n) * factorial(m - n));
return x;
}
In this case I would start to simplify the equation. In your example you're looking for 500 choose 2, which is 500!/498!/2!. This can be easily changed to 500*499/2, which can be calculated.
In general terms if you have n choose k, you only need to calculate a "partial factorial" from n to max(k, n-k) and then divide by min(k, n-k)! due to the results being mirrored. This makes the calculation much easier.
Also in certain cases you could start dividing with the min(k, n-k)! while multiplying, but that will lead to remainders etc.
Use the Pascal's triangle property:
C(n,k) = C(n - 1, k) + C(n - 1, k - 1) and dynamic programming. No factorials involved.
The triangle of Pascal being:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
You don't need to use factorials. If k>n/2, then use C(n,k)=C(n,n-k). Then use that C(n,0)=1 and for k>0, C(n,k) = C(n,k-1) * (n-k+1)/k. This lets you compute almost as many binomial coefficients as the dynamic programming method but it takes linear time (Theta(min(n-k,k))) and constant space instead of quadratic time and linear space.
See this past question: How to efficiently calculate a row in pascal's triangle?
public static long combination(int n, int k)
{
if (n-k < k)
return combination(n,n-k);
if (k < 0)
return 0;
long result = 1;
for (int i=1; i<=k; i++)
{
result *= n-i+1;
result /=i;
}
return result;
}
This may overflow if the answer times n exceeds the maximum long. So, if you expect the answer to fit in a 32 bit int and you have 64 bit longs, then this should not overflow. To avoid overflowing, use BigIntegers instead of longs.
You need to write a new function, lets call it FactorialMoverN
int FactorialMOverN(int m, int n)
{
int x = 1;
for (int i = m; i > n; i--)
x = x * i;
return x;
}
Then change your combination function to
x = FactorialMOverN(m,n) * factorial(m - n));
This should help. If it doesn't help, then you need to use a different variable type, or rethink your problem.
Thanks to Sami, I can see that the above function is in error. The 500 choose 2 needs to be calculated via
int MChooseN(int m, int n)
{
int x = 1;
for (int i = m; i > (m-n); i--)
x = x * i;
return x;
}
The above will take 500, 2 and return 500*499, the previous would have taken 500,2 and returned 500*499*498...5*4*3 which is not what you wanted.
Anyway, the above is the best you can get.
public static void Main()
{
EvenNumbers();
}
public static void EvenNumbers()
{
int written = int.Parse(Console.ReadLine());
for (int i = 0; i <= written; i++)
{
if (i % 2 == 1)
continue;
Console.WriteLine(i);
}
}
}
}
Yes I'm aware I've declared the code in a different method from the main method despite with a program this simple there being no need to its just for simple practice. I'm just wondering as you can see in the code it detects the input of the user and then from that input uses a for loop and counts up to it evenly. However, I want it to count up to it by odds if I put an odd number in. How could I do this?
Check for i % 2 != written % 2.
To print odd or even numbers, the line if (i % 2 == x) needs to have x=1 to print even numbers and x=0 to print odd numbers. If you take written % 2 you will get 0 if it is even and 1 if it is odd. Since you want to print even numbers if the input number is even and odd numbers if the input is odd, you store a number in the variable modNumber that you will then use in place of x in if (i % 2 == x). The line int modNumber = written % 2 == 1 ? 0 : 1 in English means "The int modNumber equals 0 if written % 2 == 1, otherwise it equals 1".
public static void EvenNumbers()
{
int written = int.Parse(Console.ReadLine());
int modNumber = written % 2 == 1 ? 0 : 1;
for (int i = 0; i <= written; i++)
{
if (i % 2 == modNumber)
continue;
Console.WriteLine(i);
}
}
You just need to count by twos. That will work for either even or odd numbers. For odd numbers, you need to start at 1, and for even numbers, you need to start at 0. You can easily figure out which you need by doing a single mod operation. x % 2 will be 1 for odd numbers, and zero for even numbers.
public static void Count()
{
int written = int.Parse(Console.ReadLine());
for (int i = written % 2; i <= written; i += 2)
{
Console.WriteLine(i);
}
}
If I have a standard for loop is there a more efficient way to omit certain occurances?
For example:
A:
for (int i = 0; i < n; i++)
{
if (i != n / 2 && i != n / 3 && i != n / 4)
{
val += DoWork(i);
}
else
{
continue;
}
}
B:
for (int i = 0; i < n / 4; i++)
{
val += DoWork(i); ;
}
for (int i = n / 4 + 1; i < n / 3; i++)
{
val += DoWork(i);
}
for (int i = n / 3 + 1; i < n / 2; i++)
{
val += DoWork(i);
}
for (int i = n / 2 + 1; i < n; i++)
{
val += DoWork(i);
}
C:
for (int i = 0; i < n; i++)
{
if (i == n / 2 || i == n / 3 || i == n / 4)
{
continue;
}
else
{
val += DoWork(i);
}
}
For n = int.MaxValue the results were as follows:
A Results: 57498 milliseconds.
B Results: 42204 milliseconds.
C Results: 57643 milliseconds.
EDIT BASED ON #Churk 's answer.
I added another test case method D as follows:
D:
for (int i = 0; i < n; i = (i != n / 2 -1 && i != n / 3 -1 && i != n / 4-1) ? i+1: i+2)
{
val += DoWork(i);
}
and got the following results:
A Results: 56355 milliseconds.
B Results: 40612 milliseconds.
C Results: 56214 milliseconds.
D Results: 51810 milliseconds.
Edit2: After pre-calculating values for n/2 n/3 and n/4 outside the loop got:
A Results: 50873 milliseconds.
B Results: 39514 milliseconds.
C Results: 51167 milliseconds.
D Results: 42808 milliseconds.
The D loop seems to be close again to the "unrolling" of B, with A and C still taking significantly more time.
Which are about what I expected, as far as comparisons between each of the methods.
My question is, is there a more efficient way of doing this?
It depends a bit on the context. One possiblitiy in many scenarios is to cheat. So instead of omitting the numbers, just include them and later reverse the result from the numbers you didn't want:
for (int i = 0; i < n; i++)
{
val += DoWork(i);
}
val -= DoWork(i/2);
val -= DoWork(i/3);
val -= DoWork(i/4);
The time you save from comparisons might outweigh the results from calculating some numbers twice, depending on how expensive the DoWork operation is.
Embed your secondary condition into you for loop
Untested:
for (int i = 0; i < n || (i != n / 2 && i != n / 3 && i != n / 4); i++)
val += DoWork(i);
}
I think this will work as long as one of those condition is true it will keep going
First, just pause it a few times during that 40-60 seconds, so you get a fair idea what fraction of time is in DoWork. If you could even make your looping take no time at all, you'd still have to spend that part.
Now look at your comparisons.
Each one is asking a question.
If the answer to a question is almost always True or almost always False, it is an opportunity to get speedup.
(All the log(n) and n*log(n) algorithms work by making their decision points more like fair coins.)
So you can see why your B is faster. It is asking fewer questions per loop, on average.
You can make it even faster, by unrolling the loops (asking the questions even less often).
(I know, I know, compilers can unroll loops. Well, maybe. Do it yourself and you won't have to bet on it.)
You could calculate the values outside of the loop and then just skip them:
int skip1 = n/2;
int skip2 = n/3;
int skip3 = n/4;
for (int i = 0; i < n; i++)
{
if (i != skip1 && i != skip2 && i != skip3)
{
val += DoWork(i);
}
}
Not sure if this will save enough milliseconds to be worthwhile, though.
Update: I've just noticed that #surfen suggested this in the comments.
If DoWork() isn't the bottleneck, it is a small enough method to embed into the loop, so you won't need the call which costs time by itself. If DoWork() does most of the work though, you're the one wasting time :)
You can count operations...
Option A:
n checks on i in the for loop and then 3 checks on each i that isn't that value... so there's 4n operations just for the checks.
option B:
You're just looping through intervals, so you're doing n-3 operations.
option C:
Same as option A, 4n operations.
I wouldn't bother complicating code with such modifications (as many have already commented on your question)
Instead, you might want to run your DoWork simultanuously in multiple threads using Pararell.ForEach. This would have a much larger impact on performance, if your DoWork() does anything.
I have the following problem (from ProjectEuler.net - Problem 14)
The following iterative sequence is defined for the set of positive integers:
n -> n/2 (n is even)
n -> 3n + 1 (n is odd)
Using the rule above and starting with 13, we generate the following sequence:
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.
Which starting number, under one million, produces the longest chain?
NOTE: Once the chain starts the terms are allowed to go above one million.
I used:
static int road (int n)
{
int road = 0;
while (n != 1)
{
if (n % 2 == 0)
n = n / 2;
else
n = 3 * n + 1;
road++;
}
return road;
}
static void Main(string[] args)
{
int max = 0, num = 0;
for (int i = 1; i < 1000000; i++)
{
if (road(i) > max)
{
max = road(i);
num = i;
}
}
Console.WriteLine(num);
}
But no output is printed.
(I'm not going to give you a complete solution since Project Euler is intended to make you think, not us who already solved the problems.)
Try figuring out how large the values in your chain are going to be and keep in mind the limits for integral types.
function problem14(){
function r(p,n){
return cl(p)>cl(n)?p:n;
}
function c(n){
return n%2===0?n/2:3*n+1;
}
function cl(n){
var _a = 1;
var _n = n;
while(_n !== 1){
_a++;
_n = c(_n);
}
return _a;
}
var b = [];
var m = 20;
var i = 500000;
while(i < 1000000){
var _n = cl(i);
if(_n>m){
b.push(i);
m = _n;
}
i++;
}
return b.reduce(r);
}
Here is my js code.
It is not that "nothing is output", it is just running very long. If you change the upper bound of the for-loop to 100000, you will see that pretty quickly you get output. The reason it runs very long is that you use unchecked integers and you don't get an overflowexception where you should want one. Break after a few seconds an you'll see a negative n.
Try the following , i.e. with the checked keyword, it will illustrate what I mean:
// will now throw OverflowException with large n
checked
{
int road = 0;
while (n != 1)
{
if (n%2 == 0)
n = n/2;
else
n = 3*n + 1;
road++;
}
return road;
}
First, note that you are calling the road() function twice per iteration, which is a waste of processing time (and for a 'function with side effects', could have unwanted consequences).
Secondly, due to integer overflow, you can't get an answer - the value 113383, for example, ends up cycling around the same 20 or so numbers
-122, -61, -182, -91, -272, -136, -68, -34, -17, -50, -25, -74, -37, -110, -55, ,-164, -82, -41, -122
Oops!
All numbers that divide evenly into x.
I put in 4 it returns: 4, 2, 1
edit: I know it sounds homeworky. I'm writing a little app to populate some product tables with semi random test data. Two of the properties are ItemMaximum and Item Multiplier. I need to make sure that the multiplier does not create an illogical situation where buying 1 more item would put the order over the maximum allowed. Thus the factors will give a list of valid values for my test data.
edit++:
This is what I went with after all the help from everyone. Thanks again!
edit#: I wrote 3 different versions to see which I liked better and tested them against factoring small numbers and very large numbers. I'll paste the results.
static IEnumerable<int> GetFactors2(int n)
{
return from a in Enumerable.Range(1, n)
where n % a == 0
select a;
}
private IEnumerable<int> GetFactors3(int x)
{
for (int factor = 1; factor * factor <= x; factor++)
{
if (x % factor == 0)
{
yield return factor;
if (factor * factor != x)
yield return x / factor;
}
}
}
private IEnumerable<int> GetFactors1(int x)
{
int max = (int)Math.Ceiling(Math.Sqrt(x));
for (int factor = 1; factor < max; factor++)
{
if(x % factor == 0)
{
yield return factor;
if(factor != max)
yield return x / factor;
}
}
}
In ticks.
When factoring the number 20, 5 times each:
GetFactors1-5,445,881
GetFactors2-4,308,234
GetFactors3-2,913,659
When factoring the number 20000, 5 times each:
GetFactors1-5,644,457
GetFactors2-12,117,938
GetFactors3-3,108,182
pseudocode:
Loop from 1 to the square root of the number, call the index "i".
if number mod i is 0, add i and number / i to the list of factors.
realocode:
public List<int> Factor(int number)
{
var factors = new List<int>();
int max = (int)Math.Sqrt(number); // Round down
for (int factor = 1; factor <= max; ++factor) // Test from 1 to the square root, or the int below it, inclusive.
{
if (number % factor == 0)
{
factors.Add(factor);
if (factor != number/factor) // Don't add the square root twice! Thanks Jon
factors.Add(number/factor);
}
}
return factors;
}
As Jon Skeet mentioned, you could implement this as an IEnumerable<int> as well - use yield instead of adding to a list. The advantage with List<int> is that it could be sorted before return if required. Then again, you could get a sorted enumerator with a hybrid approach, yielding the first factor and storing the second one in each iteration of the loop, then yielding each value that was stored in reverse order.
You will also want to do something to handle the case where a negative number passed into the function.
The % (remainder) operator is the one to use here. If x % y == 0 then x is divisible by y. (Assuming 0 < y <= x)
I'd personally implement this as a method returning an IEnumerable<int> using an iterator block.
Very late but the accepted answer (a while back) didn't not give the correct results.
Thanks to Merlyn, I got now got the reason for the square as a 'max' below the corrected sample. althought the answer from Echostorm seems more complete.
public static IEnumerable<uint> GetFactors(uint x)
{
for (uint i = 1; i * i <= x; i++)
{
if (x % i == 0)
{
yield return i;
if (i != x / i)
yield return x / i;
}
}
}
As extension methods:
public static bool Divides(this int potentialFactor, int i)
{
return i % potentialFactor == 0;
}
public static IEnumerable<int> Factors(this int i)
{
return from potentialFactor in Enumerable.Range(1, i)
where potentialFactor.Divides(i)
select potentialFactor;
}
Here's an example of usage:
foreach (int i in 4.Factors())
{
Console.WriteLine(i);
}
Note that I have optimized for clarity, not for performance. For large values of i this algorithm can take a long time.
Another LINQ style and tying to keep the O(sqrt(n)) complexity
static IEnumerable<int> GetFactors(int n)
{
Debug.Assert(n >= 1);
var pairList = from i in Enumerable.Range(1, (int)(Math.Round(Math.Sqrt(n) + 1)))
where n % i == 0
select new { A = i, B = n / i };
foreach(var pair in pairList)
{
yield return pair.A;
yield return pair.B;
}
}
Here it is again, only counting to the square root, as others mentioned. I suppose that people are attracted to that idea if you're hoping to improve performance. I'd rather write elegant code first, and optimize for performance later, after testing my software.
Still, for reference, here it is:
public static bool Divides(this int potentialFactor, int i)
{
return i % potentialFactor == 0;
}
public static IEnumerable<int> Factors(this int i)
{
foreach (int result in from potentialFactor in Enumerable.Range(1, (int)Math.Sqrt(i))
where potentialFactor.Divides(i)
select potentialFactor)
{
yield return result;
if (i / result != result)
{
yield return i / result;
}
}
}
Not only is the result considerably less readable, but the factors come out of order this way, too.
I did it the lazy way. I don't know much, but I've been told that simplicity can sometimes imply elegance. This is one possible way to do it:
public static IEnumerable<int> GetDivisors(int number)
{
var searched = Enumerable.Range(1, number)
.Where((x) => number % x == 0)
.Select(x => number / x);
foreach (var s in searched)
yield return s;
}
EDIT: As Kraang Prime pointed out, this function cannot exceed the limit of an integer and is (admittedly) not the most efficient way to handle this problem.
Wouldn't it also make sense to start at 2 and head towards an upper limit value that's continuously being recalculated based on the number you've just checked? See N/i (where N is the Number you're trying to find the factor of and i is the current number to check...) Ideally, instead of mod, you would use a divide function that returns N/i as well as any remainder it might have. That way you're performing one divide operation to recreate your upper bound as well as the remainder you'll check for even division.
Math.DivRem
http://msdn.microsoft.com/en-us/library/wwc1t3y1.aspx
If you use doubles, the following works: use a for loop iterating from 1 up to the number you want to factor. In each iteration, divide the number to be factored by i. If (number / i) % 1 == 0, then i is a factor, as is the quotient of number / i. Put one or both of these in a list, and you have all of the factors.
And one more solution. Not sure if it has any advantages other than being readable..:
List<int> GetFactors(int n)
{
var f = new List<int>() { 1 }; // adding trivial factor, optional
int m = n;
int i = 2;
while (m > 1)
{
if (m % i == 0)
{
f.Add(i);
m /= i;
}
else i++;
}
// f.Add(n); // adding trivial factor, optional
return f;
}
I came here just looking for a solution to this problem for myself. After examining the previous replies I figured it would be fair to toss out an answer of my own even if I might be a bit late to the party.
The maximum number of factors of a number will be no more than one half of that number.There is no need to deal with floating point values or transcendent operations like a square root. Additionally finding one factor of a number automatically finds another. Just find one and you can return both by just dividing the original number by the found one.
I doubt I'll need to use checks for my own implementation but I'm including them just for completeness (at least partially).
public static IEnumerable<int>Factors(int Num)
{
int ToFactor = Num;
if(ToFactor == 0)
{ // Zero has only itself and one as factors but this can't be discovered through division
// obviously.
yield return 0;
return 1;
}
if(ToFactor < 0)
{// Negative numbers are simply being treated here as just adding -1 to the list of possible
// factors. In practice it can be argued that the factors of a number can be both positive
// and negative, i.e. 4 factors into the following pairings of factors:
// (-4, -1), (-2, -2), (1, 4), (2, 2) but normally when you factor numbers you are only
// asking for the positive factors. By adding a -1 to the list it allows flagging the
// series as originating with a negative value and the implementer can use that
// information as needed.
ToFactor = -ToFactor;
yield return -1;
}
int FactorLimit = ToFactor / 2; // A good compiler may do this optimization already.
// It's here just in case;
for(int PossibleFactor = 1; PossibleFactor <= FactorLimit; PossibleFactor++)
{
if(ToFactor % PossibleFactor == 0)
{
yield return PossibleFactor;
yield return ToFactor / PossibleFactor;
}
}
}
Program to get prime factors of whole numbers in javascript code.
function getFactors(num1){
var factors = [];
var divider = 2;
while(num1 != 1){
if(num1 % divider == 0){
num1 = num1 / divider;
factors.push(divider);
}
else{
divider++;
}
}
console.log(factors);
return factors;
}
getFactors(20);
In fact we don't have to check for factors not to be square root in each iteration from the accepted answer proposed by chris fixed by Jon, which could slow down the method when the integer is large by adding an unnecessary Boolean check and a division. Just keep the max as double (don't cast it to an int) and change to loop to be exclusive not inclusive.
private static List<int> Factor(int number)
{
var factors = new List<int>();
var max = Math.Sqrt(number); // (store in double not an int) - Round down
if (max % 1 == 0)
factors.Add((int)max);
for (int factor = 1; factor < max; ++factor) // (Exclusice) - Test from 1 to the square root, or the int below it, inclusive.
{
if (number % factor == 0)
{
factors.Add(factor);
//if (factor != number / factor) // (Don't need check anymore) - Don't add the square root twice! Thanks Jon
factors.Add(number / factor);
}
}
return factors;
}
Usage
Factor(16)
// 4 1 16 2 8
Factor(20)
//1 20 2 10 4 5
And this is the extension version of the method for int type:
public static class IntExtensions
{
public static IEnumerable<int> Factors(this int value)
{
// Return 2 obvious factors
yield return 1;
yield return value;
// Return square root if number is prefect square
var max = Math.Sqrt(value);
if (max % 1 == 0)
yield return (int)max;
// Return rest of the factors
for (int i = 2; i < max; i++)
{
if (value % i == 0)
{
yield return i;
yield return value / i;
}
}
}
}
Usage
16.Factors()
// 4 1 16 2 8
20.Factors()
//1 20 2 10 4 5
Linq solution:
IEnumerable<int> GetFactors(int n)
{
Debug.Assert(n >= 1);
return from i in Enumerable.Range(1, n)
where n % i == 0
select i;
}