Reputation: 117
I am interested with LINQ these days. I am trying to get prime numbers. I am actually did very well but my code doesn't show primes which is below Sqrt(n).
static void Main(string[] args)
{
Func<int, int, IEnumerable<int>> EnumerableRange =
(startPoint, endPoint) =>
Enumerable.Range(Math.Min(startPoint, endPoint), Math.Abs(startPoint - endPoint) + 1);
Func<int, int, bool> isFullyDivided =
(value, divisor) =>
(value % divisor).Equals(0);
int sp = 2,
ep = 100;
var query =
EnumerableRange(sp, ep)
.Where(value =>
EnumerableRange(2, (int)Math.Ceiling(Math.Sqrt(ep)))
.Any(divisor =>
isFullyDivided(value, divisor))
);
var primeNumbers =
EnumerableRange(sp, ep)
.Except(query);
foreach (var item in primeNumbers)
{
Console
.WriteLine(item);
}
Console
.Read();
}
Currently, this code incorrect leaves out the prime numbers that are less than sqrt(n)
. The code is supposed to get the primes between 2 and 100. Instead it only prints prime numbers 11 and above. The primes 2, 3, 5, 7
are missing.
Upvotes: 2
Views: 1898
Reputation: 117
Best solution :
var query =
EnumerableRange(sp, ep)
.Where(value =>
EnumerableRange(2, (int)Math.Ceiling(Math.Sqrt(value)))
.Any(divisor =>
!value.Equals(divisor) &&
isFullyDivided(value, divisor))
);
Math.Floor is wrong. Correct one is Math.Ceiling.
Upvotes: 0
Reputation: 152521
You constraint of divisors is incorrect - you are looking at divisors between 2 and Sqrt(ep)
(10), when you only need to check divisors between 2 and Sqrt(value)
:
var query =
EnumerableRange(sp, ep)
.Where(value => V----------
EnumerableRange(2, (int)Math.Ceiling(Math.Sqrt(value)))
.Any(divisor =>
isFullyDivided(value, divisor))
);
That is why your primes start at 11, because your divisors go up to 10 which would include the value itself. @ryanyuyu's answer also solves the same problem but in a different way. Your code will still be checking unnecessary divisors.
Upvotes: 2
Reputation: 6486
You have a logic problem. Everything can evenly divide itself, so you should check that the value != divisor
. Otherwise you will incorrectly exclude the numbers that divide themselves (for example 5 % 5 == 0
).
var query =
EnumerableRange(sp, ep)
.Where(value =>
EnumerableRange(2, (int)Math.Ceiling(Math.Sqrt(ep)))
.Any(divisor =>
value != divisor && //This is the logic you are missing
isFullyDivided(value, divisor))
);
Upvotes: 2