33

I want to find the prime number between 0 and a long variable but I am not able to get any output.

The program is

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication16
{
    class Program
    {
        void prime_num(long num)
        {
            bool isPrime = true;
            for (int i = 0; i <= num; i++)
            {
                for (int j = 2; j <= num; j++)
                {
                    if (i != j && i % j == 0)
                    {
                        isPrime = false;
                        break;
                    }
                }
                if (isPrime)
                {
                    Console.WriteLine ( "Prime:" + i );
                }
                isPrime = true;
            }
        }

        static void Main(string[] args)
        {
            Program p = new Program();
            p.prime_num (999999999999999L);
            Console.ReadLine();
        }
    }
}

Can any one help me out and find what is the possible error in the program?

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
sandy101
  • 3,395
  • 3
  • 23
  • 19
  • Which project template was used to create this project. – Alexandre Brisebois Oct 02 '09 at 15:10
  • 8
    Homework alert !! – whatnick Oct 02 '09 at 15:13
  • Do you get any output if you put in a small number to start with, such as 10? – Eric J. Oct 02 '09 at 15:14
  • 12
    Probably homework, nothing wrong with that as long as the asker has tried to answer the homework problem and is stuck on a specific issue (as seems to be the case here). – Eric J. Oct 02 '09 at 15:15
  • @George Stocker: this is the most patological example I've seen of this problem :S – Esteban Küber Oct 02 '09 at 15:16
  • Even if you stick to the naive algorithm, at least stop searching at the square root. – Tamas Czinege Oct 02 '09 at 15:16
  • 3
    How long will this thing actually take? 999999999999999L is quite a big number? – Guillermo Phillips Oct 02 '09 at 15:31
  • @GuillermoPhillips, it will take lifetimes, even when fixed as per the answers below, nor is the purpose of generating all those prime numbers explained. If the purpose is summing them, finding the first occurrence of gaps, doubles, triples, and so on, then the only feasible approach would be to write a highly efficient multi-processor page-segmented version of the Sieve of Eratosthenes, which would take a month or two on a modern high-end desktop computer but could be scaled to run on hundreds of thousands of cores of a supercomputer to run in seconds. – GordonBGood Nov 16 '15 at 01:32

28 Answers28

83

You can do this faster using a nearly optimal trial division sieve in one (long) line like this:

Enumerable.Range(0, Math.Floor(2.52*Math.Sqrt(num)/Math.Log(num))).Aggregate(
    Enumerable.Range(2, num-1).ToList(), 
    (result, index) => { 
        var bp = result[index]; var sqr = bp * bp;
        result.RemoveAll(i => i >= sqr && i % bp == 0); 
        return result; 
    }
);

The approximation formula for number of primes used here is π(x) < 1.26 x / ln(x). We only need to test by primes not greater than x = sqrt(num).

Note that the sieve of Eratosthenes has much better run time complexity than trial division (should run much faster for bigger num values, when properly implemented).

Will Ness
  • 70,110
  • 9
  • 98
  • 181
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 7
    Why was this downvoted? It answers the question (How can I make this better?) – SLaks Oct 02 '09 at 15:20
  • 12
    It looks like the OP has a specific homework assignment. If he submits your solution, the instructor will consider it cheating. – Jon B Oct 02 '09 at 15:24
  • 4
    Yes, amazing that the principle was first described over 2000 years ago. – UpTheCreek Oct 02 '09 at 15:24
  • 1
    (fyi - I'm not the one who -1'd you) – Jon B Oct 02 '09 at 15:24
  • 26
    And the instructor will be quite right to. Using any other answer can also be called cheating. However, it still answers the question. – SLaks Oct 02 '09 at 15:25
  • I think I might have downvoted accidentally - there was a lot of activity on this page. – Cade Roux Oct 02 '09 at 15:26
  • I removed the down vote, but it won't let me up vote now even after changing the answer again... – Cade Roux Oct 02 '09 at 15:27
  • 2
    The answer has always been there , he is not doing a major research project. – whatnick Oct 02 '09 at 15:28
  • 1
    Technically this returns more answers than num. – Cameron MacFarland Oct 02 '09 at 15:47
  • 1
    And returns non-primes beyond num. – Cameron MacFarland Oct 02 '09 at 15:53
  • How is this different than the OP google-ing or live-ing the question and getting an answer. No reason to down vote an excellent way to solve a probem coz you're trigger happy! – Abhijeet Patel Oct 02 '09 at 17:43
  • 1
    It's broken. For example, if n = 3 then it returns 49, which is not prime. – Cameron MacFarland Oct 03 '09 at 05:57
  • 2
    Doesn't this have close to quadratic complexity? Eratosthenes is a different algorithm and is much faster than this. – Accipitridae Oct 07 '09 at 18:13
  • How to use this piece of code.Can anybody give the full program code. – Vinod May 17 '11 at 07:27
  • At no point does the sieve *of Eratosthenes* calculate remainders to test and remove candidate numbers by. It just doesn't. – Will Ness Apr 19 '12 at 07:32
  • This answer is great, unfortunately it's not quite correct. The first range should be from 2 to `num` and, likewise, the second range should be from 2 to `num`, and the `RemoveAll` line should be `result.RemoveAll(i => i > index && i % index == 0);` – N_A Aug 23 '12 at 17:02
  • 1) THis is not SoE but rather a bounded version of the David Turner Sieve (1975) as per (this link)[http://en.literateprograms.org/Sieve_of_Eratosthenes_(Haskell)], as it culls by (not optimized) **Trial Division** and not by simple addition of offsets by primes as per the true SoE. 2) As for Turner, this does not limit the tests to only those found primes less than the square root of the top number sieved nor does it start at the square of each prime found. These optimizations can be added, but the program is also more complex than it needs to be in use of 2 ranges and the Aggregate method. – GordonBGood Dec 06 '13 at 08:44
  • @mydogisbox I think you've missed the point of what this code was trying to achieve: `result` is culled on each step; using `result[index]`, with `index = 0,1,2,3...`, progressively tests and culls the `result` list by 2,3,5,7,11,... . You're correct that the ranges are wrong though, it seems. – Will Ness Dec 30 '13 at 11:37
  • @WillNess Ah, right you are. Somehow I missed that it was working with the filtered list. – N_A Dec 30 '13 at 16:31
  • @mydogisbox or rather it was filtering the list as it went from one source element to the next. What do you think of this [proposed edit](http://pastebin.com/nuvMQ6jn)? Is it OK? – Will Ness Dec 30 '13 at 17:25
  • @WillNess Isn't the first range still incorrect? 0 and 1 are not prime. – N_A Dec 30 '13 at 17:31
  • @WillNess: Also, it still iterates over the entire list every time. `RemoveAll()` cannot do this optimally. – SLaks Dec 30 '13 at 17:32
  • @SLaks right, but the amount of times RemoveAll is run will be greatly diminished, nearly optimal. It should be PrimePi[sqrt(num)] really. Would you edit so I can un-upvote? (and of course for num=10^15 it won't ever finish, but that's besides the point...) Or should I (edit)?... – Will Ness Dec 30 '13 at 17:35
  • @mydogisbox no, first range is used as indices into the `result`. Lists start at index 0. – Will Ness Dec 30 '13 at 17:36
  • @WillNess Ah, that's what I get for not spending enough time understanding what it's doing. – N_A Dec 30 '13 at 17:41
  • @SLaks BTW that it starts from the start each time, doesn't change the complexity, because the prefix is on order of ~ `Sqrt` of total length - *with my proposed edit*, that is. You could say then, that it is a *nearly optimal* trial division sieve. Most important is to limit the number of iterations from `num` to [`PrimePi[Sqrt[num]]`](http://www.wolframalpha.com/input/?i=PrimePi%5BSqrt%5B1000000%5D%5D). – Will Ness Dec 30 '13 at 17:45
  • @WillNess: I originally wrote this code to find the first N primes rather than primes below N. – SLaks Dec 30 '13 at 17:48
  • @WillNess: I'm not saying you shouldn't edit; I was explaining the original code. Feel free to edit it. – SLaks Dec 30 '13 at 17:54
  • @WillNess, it is even more "nearly optimal trial division" performance if "i >= sqr" rather than "i > i" and "i % bp" instead of "i % result[index]" where "var bp = result[index]; var sqr = bp * bp;" are defined before the results.RemoveAll() statement, in which case it will be over twice as fast. There is no need to check the lower numbers as they have already been cleared by lower value base primes. Other than the Optimized Trial Division performance, the limitation as compared to the question code is the amount of memory used for the List so it's limited to ranges up to about 500,000,000. – GordonBGood Jan 01 '14 at 07:21
  • @GordonBGood was [this](http://stackoverflow.com/questions/1510124/program-to-find-prime-numbers/1510186#comment31265659_1510186) wrong?... Do you see the same speedup factor for several `num` values, or does it increase? – Will Ness Jan 01 '14 at 09:11
  • @WillNess, it isn't wrong, just a little slower than it needs to be. As you've written it for my machine, times are 0.012, 0.179, and 3.6 seconds for up to 100,000, up to one million, and up to 10 million, respectively, where they are 0.008, 0.109, and 2.116 seconds with the modification. The speed-up is mostly due to accessing the List/Array once instead of twice in the inner loop, as DotNet doesn't optimize for lambda expressions hardly at all. – GordonBGood Jan 01 '14 at 16:14
  • @GordonBGood [empirically](https://gist.github.com/WillNess/8217144), there's a very small penalty in complexity for starting from the start and not from the squares, ~ N^0.016 (on low ranges, like here). But the constant factor is about 1.2...1.25 (counting the divisions); that's *before* the effect of the auxiliary vars. Your run times data is in agreement, more or less. So, a good catch! :) – Will Ness Jan 02 '14 at 10:15
  • Thanks for the quick and easy Prime Number generator! I used your code in [this SO thread](http://stackoverflow.com/a/31897007/2330053) to "visualize" the Prime Numbers. – Idle_Mind Aug 08 '15 at 18:09
25

Try this:

void prime_num(long num)
{

    // bool isPrime = true;
    for (long i = 0; i <= num; i++)
    {
        bool isPrime = true; // Move initialization to here
        for (long j = 2; j < i; j++) // you actually only need to check up to sqrt(i)
        {
            if (i % j == 0) // you don't need the first condition
            {
                isPrime = false;
                break;
            }
        }
        if (isPrime)
        {
            Console.WriteLine ( "Prime:" + i );
        }
        // isPrime = true;
    }
}
pantelif
  • 8,524
  • 2
  • 33
  • 48
Cade Roux
  • 88,164
  • 40
  • 182
  • 265
  • +1 a proper fix (almost) for the problem: there wasn't **"any output"** because of using **`num`** upper limit in the inner loop; this answer changes it to the inefficient, but *not insane*, `i`. Obviously the intent of the program is just to print a steady stream of primes, not to **print** them ***all***... And the original code didn't print **any** because of the insane test `1%2, 1%3, ... 1%(10^15-1)` which were of course all non-zero, so eventually it *would* report 1 as prime. One more thing: this code here does report 0 and 1 as primes though. :) `i` should start from 2 too. – Will Ness Apr 18 '12 at 21:26
  • @WillNess, as you say there was a problem with the question code in that it would do an insane number of ridiculous prime checks, the real reason that the question code didn't produce **any output at all** is actually the mixing of long range check limit variables and integer loop variables (automatically extended to long for the comparison) which cause is exactly as the questioner experienced: the inner checking loop never exits because the range of the loop variable is less than the range checked, thus no output is ever produced. – GordonBGood Dec 30 '13 at 09:35
  • 1
    @GordonBGood 2^32 < 10^10; if there was an INT range wrap-around, `j` would reach 0 eventually and cause div by zero in `1%j`. i7 core is a 100 gigaFLOPS chip, 100*10^9 , so this should've happened in under a second. Maybe, in C#, `int`s are 64-bit? Then a run to 10^15 would happen, taking ~ 20 minutes...2 hours time, for `i=1`. – Will Ness Dec 30 '13 at 10:24
  • @WillNess, well, the divide operation takes about 50 clock cycles itself, so the time to loop around to the divide by zero state will be several 10's of seconds; however, it never actually gets to zero as every number tested has a modulo of zero when tested for -1, thus the loop spins forever never finding any primes at all (they are all evenly divisible by -1, which takes 10's of seconds per trial). – GordonBGood Dec 31 '13 at 00:28
  • @GordonBGood aha, `-1`, nice catch! :) – Will Ness Dec 31 '13 at 00:29
  • @WillNess, I don't know if you've seen it, but I [submitted an answer to an old question](http://stackoverflow.com/a/20559687/549617) as well as [here about multithreading](http://stackoverflow.com/a/18885065/549617) which is a maximally optimized C# version of the SoE that uses all of the principles you so often espouse: page segmentation, double-staged primes production, wheel factorization (extreme), and even adds multi-processing per segment page. It is a little long, but worth it in being actually able to process this huge range of numbers in a few months on an i7 (primesieve 30 days). – GordonBGood Dec 31 '13 at 03:15
  • @GordonBGood wow, C# only few times slower than primesieve, that's an achievement! C# is not my language though but it will be interesting to read your code. About all the optimizations, I'm just a transmitter. :) I found the "postponement" fix to Turner's sieve on my own few years back, as I'm sure/know did (many) others, so that sparked some interest. Cheers! :) – Will Ness Dec 31 '13 at 09:40
  • @WillNess, although the C# code uses some functional forms of code, I haven't yet converted the algorithm to a fully functional F# form (fully functional other than the mutable array composite number representation culling operations), which will be just slightly slower than C# due to the few stacked call/return operations I won't be able to avoid. It would be interesting to implement in other functional languages such as Haskell, although I don't know how to specify and use mutable arrays in Haskell. – GordonBGood Jan 01 '14 at 02:56
10

You only need to check odd divisors up to the square root of the number. In other words your inner loop needs to start:

for (int j = 3; j <= Math.Sqrt(i); j+=2) { ... }

You can also break out of the function as soon as you find the number is not prime, you don't need to check any more divisors (I see you're already doing that!).

This will only work if num is bigger than two.

No Sqrt

You can avoid the Sqrt altogether by keeping a running sum. For example:

int square_sum=1;
for (int j=3; square_sum<i; square_sum+=4*(j++-1)) {...}

This is because the sum of numbers 1+(3+5)+(7+9) will give you a sequence of odd squares (1,9,25 etc). And hence j represents the square root of square_sum. As long as square_sum is less than i then j is less than the square root.

Guillermo Phillips
  • 2,176
  • 1
  • 23
  • 40
  • @GuillermoPhillips, if one wanted to use the square_sum option, the correct and more efficient loop (only divide by odd numbers; also note the check **up to and including the square root**) would be for (int j=3, square_sum=9; square_sum <= i; square_sum+=4((j+=2)-1)) {...} – GordonBGood Dec 30 '13 at 10:09
  • @GuillermoPhillips, I don't think the square_sum idea actually works all that well in practice as although it takes up to about 24 CPU clocks to compute (int)Math.Sqrt((double)i), this can be done just once for each value of 'i', whereas the square_sum computation requires about one CPU clock **per loop of 'j'**; this means that the square root computation actually takes less time than the running square_sum computation once 'i' gets up to a value of a thousand or so. – GordonBGood Dec 30 '13 at 23:41
10

People have mentioned a couple of the building blocks toward doing this efficiently, but nobody's really put the pieces together. The sieve of Eratosthenes is a good start, but with it you'll run out of memory long before you reach the limit you've set. That doesn't mean it's useless though -- when you're doing your loop, what you really care about are prime divisors. As such, you can start by using the sieve to create a base of prime divisors, then use those in the loop to test numbers for primacy.

When you write the loop, however, you really do NOT want to us sqrt(i) in the loop condition as a couple of answers have suggested. You and I know that the sqrt is a "pure" function that always gives the same answer if given the same input parameter. Unfortunately, the compiler does NOT know that, so if use something like '<=Math.sqrt(x)' in the loop condition, it'll re-compute the sqrt of the number every iteration of the loop.

You can avoid that a couple of different ways. You can either pre-compute the sqrt before the loop, and use the pre-computed value in the loop condition, or you can work in the other direction, and change i<Math.sqrt(x) to i*i<x. Personally, I'd pre-compute the square root though -- I think it's clearer and probably a bit faster--but that depends on the number of iterations of the loop (the i*i means it's still doing a multiplication in the loop). With only a few iterations, i*i will typically be faster. With enough iterations, the loss from i*i every iteration outweighs the time for executing sqrt once outside the loop.

That's probably adequate for the size of numbers you're dealing with -- a 15 digit limit means the square root is 7 or 8 digits, which fits in a pretty reasonable amount of memory. On the other hand, if you want to deal with numbers in this range a lot, you might want to look at some of the more sophisticated prime-checking algorithms, such as Pollard's or Brent's algorithms. These are more complex (to put it mildly) but a lot faster for large numbers.

There are other algorithms for even bigger numbers (quadratic sieve, general number field sieve) but we won't get into them for the moment -- they're a lot more complex, and really only useful for dealing with really big numbers (the GNFS starts to be useful in the 100+ digit range).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • +1 Interesting summary of prime algorithms, made me wikipedia and wolfram for a bit. Would love this post edited to include links. – whatnick Oct 03 '09 at 04:22
  • You are not quite correct as to "do NOT want to use sqrt(i) in the loop condition" as there are ways to make that clear to both the compiler and the code reader by computing the limit once **outside the actual loop range check** as I did in [my answer](http://stackoverflow.com/a/20421154/549617). – GordonBGood Dec 30 '13 at 09:49
8

First step: write an extension method to find out if an input is prime

public static bool isPrime(this int number ) {

    for (int i = 2; i < number; i++) { 
        if (number % i == 0) { 
            return false; 
        } 
    }

    return true;   
}

2 step: write the method that will print all prime numbers that are between 0 and the number input

public static void getAllPrimes(int number)
{
    for (int i = 0; i < number; i++)
    {
        if (i.isPrime()) Console.WriteLine(i);
    }
}
TotoroTotoro
  • 17,524
  • 4
  • 45
  • 76
Bamara Coulibaly
  • 729
  • 1
  • 8
  • 7
  • your `isPrime` will return `true` for 0, 1, and for any negative number. So the loop inside `getAllPrimes` should start from `int i = 2;` , at least. – Will Ness Apr 18 '12 at 21:55
  • no, no, the `return true;` should be the next statement after the `for` statement, as it is right now (just the text indentation isn't right). but the function `isPrime` as written, assumes `2 <= number`. In other cases it won't work properly. So wherever you use it, make sure you test a number greater than 1 with it. It is a sensible choice too, since no number less than 2 is a prime, so need to check those numbers. That means, just change your starting value for `i` in the loop of `getAllPrimes`, to start not from `0`, but from `2`. If not, your program will show 0 and 1 as prime numbers. – Will Ness May 04 '12 at 07:27
  • typo: "so ***no*** need to check those numbers" (under 2) for primality. – Will Ness May 04 '12 at 08:56
  • You only need to check up to the square root of `number` in `isPrime`. – Wai Ha Lee Jan 26 '16 at 10:09
  • you could run the loop till "i <= number / 2" in isPrime() function. Because in case of number = 19, your for loop will iterate till i = 18. – Naphstor May 22 '16 at 18:17
7

It may just be my opinion, but there's another serious error in your program (setting aside the given 'prime number' question, which has been thoroughly answered).

Like the rest of the responders, I'm assuming this is homework, which indicates you want to become a developer (presumably).

You need to learn to compartmentalize your code. It's not something you'll always need to do in a project, but it's good to know how to do it.

Your method prime_num(long num) could stand a better, more descriptive name. And if it is supposed to find all prime numbers less than a given number, it should return them as a list. This makes it easier to seperate your display and your functionality.

If it simply returned an IList containing prime numbers you could then display them in your main function (perhaps calling another outside function to pretty print them) or use them in further calculations down the line.

So my best recommendation to you is to do something like this:

public void main(string args[])
{
    //Get the number you want to use as input
    long x = number;//'number' can be hard coded or retrieved from ReadLine() or from the given arguments

    IList<long> primes = FindSmallerPrimes(number);

    DisplayPrimes(primes);
}

public IList<long> FindSmallerPrimes(long largestNumber)
{
    List<long> returnList = new List<long>();
    //Find the primes, using a method as described by another answer, add them to returnList
    return returnList;
}

public void DisplayPrimes(IList<long> primes)
{
    foreach(long l in primes)
    {
        Console.WriteLine ( "Prime:" + l.ToString() );
    }
}

Even if you end up working somewhere where speration like this isn't needed, it's good to know how to do it.

Jeff
  • 2,835
  • 3
  • 41
  • 69
  • 2
    Although other people have answered this question, I find your answer to be quite useful to the OP in the sense that it teaches him a little bit about separation of concerns in programming. +1 – Hallaghan Jan 25 '11 at 17:28
7

EDIT_ADD: If Will Ness is correct that the question's purpose is just to output a continuous stream of primes for as long as the program is run (pressing Pause/Break to pause and any key to start again) with no serious hope of every getting to that upper limit, then the code should be written with no upper limit argument and a range check of "true" for the first 'i' for loop. On the other hand, if the question wanted to actually print the primes up to a limit, then the following code will do the job much more efficiently using Trial Division only for odd numbers, with the advantage that it doesn't use memory at all (it could also be converted to a continuous loop as per the above):

static void primesttt(ulong top_number) {
  Console.WriteLine("Prime:  2");
  for (var i = 3UL; i <= top_number; i += 2) {
    var isPrime = true;
    for (uint j = 3u, lim = (uint)Math.Sqrt((double)i); j <= lim; j += 2) {
      if (i % j == 0)  {
        isPrime = false;
        break;
      }
    }
    if (isPrime) Console.WriteLine("Prime:  {0} ", i);
  }
}

First, the question code produces no output because of that its loop variables are integers and the limit tested is a huge long integer, meaning that it is impossible for the loop to reach the limit producing an inner loop EDITED: whereby the variable 'j' loops back around to negative numbers; when the 'j' variable comes back around to -1, the tested number fails the prime test because all numbers are evenly divisible by -1 END_EDIT. Even if this were corrected, the question code produces very slow output because it gets bound up doing 64-bit divisions of very large quantities of composite numbers (all the even numbers plus the odd composites) by the whole range of numbers up to that top number of ten raised to the sixteenth power for each prime that it can possibly produce. The above code works because it limits the computation to only the odd numbers and only does modulo divisions up to the square root of the current number being tested.

This takes an hour or so to display the primes up to a billion, so one can imagine the amount of time it would take to show all the primes to ten thousand trillion (10 raised to the sixteenth power), especially as the calculation gets slower with increasing range. END_EDIT_ADD

Although the one liner (kind of) answer by @SLaks using Linq works, it isn't really the Sieve of Eratosthenes as it is just an unoptimised version of Trial Division, unoptimised in that it does not eliminate odd primes, doesn't start at the square of the found base prime, and doesn't stop culling for base primes larger than the square root of the top number to sieve. It is also quite slow due to the multiple nested enumeration operations.

It is actually an abuse of the Linq Aggregate method and doesn't effectively use the first of the two Linq Range's generated. It can become an optimized Trial Division with less enumeration overhead as follows:

static IEnumerable<int> primes(uint top_number) {
  var cullbf = Enumerable.Range(2, (int)top_number).ToList();
  for (int i = 0; i < cullbf.Count; i++) {
    var bp = cullbf[i]; var sqr = bp * bp; if (sqr > top_number) break;
    cullbf.RemoveAll(c => c >= sqr && c % bp == 0);
  } return cullbf; }

which runs many times faster than the SLaks answer. However, it is still slow and memory intensive due to the List generation and the multiple enumerations as well as the multiple divide (implied by the modulo) operations.

The following true Sieve of Eratosthenes implementation runs about 30 times faster and takes much less memory as it only uses a one bit representation per number sieved and limits its enumeration to the final iterator sequence output, as well having the optimisations of only treating odd composites, and only culling from the squares of the base primes for base primes up to the square root of the maximum number, as follows:

static IEnumerable<uint> primes(uint top_number) {
  if (top_number < 2u) yield break;
  yield return 2u; if (top_number < 3u) yield break;
  var BFLMT = (top_number - 3u) / 2u;
  var SQRTLMT = ((uint)(Math.Sqrt((double)top_number)) - 3u) / 2u;
  var buf = new BitArray((int)BFLMT + 1,true);
  for (var i = 0u; i <= BFLMT; ++i) if (buf[(int)i]) {
      var p = 3u + i + i; if (i <= SQRTLMT) {
        for (var j = (p * p - 3u) / 2u; j <= BFLMT; j += p)
          buf[(int)j] = false; } yield return p; } }

The above code calculates all the primes to ten million range in about 77 milliseconds on an Intel i7-2700K (3.5 GHz).

Either of the two static methods can be called and tested with the using statements and with the static Main method as follows:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

static void Main(string[] args) {
  Console.WriteLine("This program generates prime sequences.\r\n");

  var n = 10000000u;

  var elpsd = -DateTime.Now.Ticks;

  var count = 0; var lastp = 0u;
  foreach (var p in primes(n)) { if (p > n) break; ++count; lastp = (uint)p; }

  elpsd += DateTime.Now.Ticks;
  Console.WriteLine(
    "{0} primes found <= {1}; the last one is {2} in {3} milliseconds.",
    count, n, lastp,elpsd / 10000);

  Console.Write("\r\nPress any key to exit:");
  Console.ReadKey(true);
  Console.WriteLine();
}

which will show the number of primes in the sequence up to the limit, the last prime found, and the time expended in enumerating that far.

EDIT_ADD: However, in order to produce an enumeration of the number of primes less than ten thousand trillion (ten to the sixteenth power) as the question asks, a segmented paged approach using multi-core processing is required but even with C++ and the very highly optimized PrimeSieve, this would require something over 400 hours to just produce the number of primes found, and tens of times that long to enumerate all of them so over a year to do what the question asks. To do it using the un-optimized Trial Division algorithm attempted, it will take super eons and a very very long time even using an optimized Trial Division algorithm as in something like ten to the two millionth power years (that's two million zeros years!!!).

It isn't much wonder that his desktop machine just sat and stalled when he tried it!!!! If he had tried a smaller range such as one million, he still would have found it takes in the range of seconds as implemented.

The solutions I post here won't cut it either as even the last Sieve of Eratosthenes one will require about 640 Terabytes of memory for that range.

That is why only a page segmented approach such as that of PrimeSieve can handle this sort of problem for the range as specified at all, and even that requires a very long time, as in weeks to years unless one has access to a super computer with hundreds of thousands of cores. END_EDIT_ADD

GordonBGood
  • 3,467
  • 1
  • 37
  • 45
5

Smells like more homework. My very very old graphing calculator had a is prime program like this. Technnically the inner devision checking loop only needs to run to i^(1/2). Do you need to find "all" prime numbers between 0 and L ? The other major problem is that your loop variables are "int" while your input data is "long", this will be causing an overflow making your loops fail to execute even once. Fix the loop variables.

whatnick
  • 5,400
  • 3
  • 19
  • 35
  • Actually, the mixing of long limit variables and integer loop variables will cause is exactly as the questioner experienced: the loop variable (automatically extended to a long for the comparison) is less than the range checked as designated by the long variable. This makes the inner 'j' loop test all numbers up to int.MaxValue (two billion plus) then roll over to starting at int.MinValue (negative two billion minus) and when that loop variable 'j' gets back up to -1, the loop will break out because all numbers are evenly divisible by -1, thus classed as non-prime and no results are output. – GordonBGood Dec 31 '13 at 02:38
2

One line code in C# :-

Console.WriteLine(String.Join(Environment.NewLine, 
    Enumerable.Range(2, 300)
        .Where(n => Enumerable.Range(2, (int)Math.Sqrt(n) - 1)
        .All(nn => n % nn != 0)).ToArray()));                                    
Lukas Winzenried
  • 1,919
  • 1
  • 14
  • 22
2

The Sieve of Eratosthenes answer above is not quite correct. As written it will find all the primes between 1 and 1000000. To find all the primes between 1 and num use:

private static IEnumerable Primes01(int num)
{
    return Enumerable.Range(1, Convert.ToInt32(Math.Floor(Math.Sqrt(num))))
        .Aggregate(Enumerable.Range(1, num).ToList(),
        (result, index) =>
            {
                result.RemoveAll(i => i > result[index] && i%result[index] == 0);
                return result;
            }
        );
}

The seed of the Aggregate should be range 1 to num since this list will contain the final list of primes. The Enumerable.Range(1, Convert.ToInt32(Math.Floor(Math.Sqrt(num)))) is the number of times the seed is purged.

darren
  • 193
  • 8
1

so this is basically just two typos, one, the most unfortunate, for (int j = 2; j <= num; j++) which is the reason for the unproductive testing of 1%2,1%3 ... 1%(10^15-1) which goes on for very long time so the OP didn't get "any output". It should've been j < i; instead. The other, minor one in comparison, is that i should start from 2, not from 0:

for( i=2; i <= num; i++ )
{
    for( j=2; j < i; j++ ) // j <= sqrt(i) is really enough
....

Surely it can't be reasonably expected of a console print-out of 28 trillion primes or so to be completed in any reasonable time-frame. So, the original intent of the problem was obviously to print out a steady stream of primes, indefinitely. Hence all the solutions proposing simple use of sieve of Eratosthenes are totally without merit here, because simple sieve of Eratosthenes is bounded - a limit must be set in advance.

What could work here is the optimized trial division which would save the primes as it finds them, and test against the primes, not just all numbers below the candidate.

Second alternative, with much better complexity (i.e. much faster) is to use a segmented sieve of Eratosthenes. Which is incremental and unbounded.

Both these schemes would use double-staged production of primes: one would produce and save the primes, to be used by the other stage in testing (or sieving), much above the limit of the first stage (below its square of course - automatically extending the first stage, as the second stage would go further and further up).

Community
  • 1
  • 1
Will Ness
  • 70,110
  • 9
  • 98
  • 181
1

ExchangeCore Forums have a good console application listed that looks to write found primes to a file, it looks like you can also use that same file as a starting point so you don't have to restart finding primes from 2 and they provide a download of that file with all found primes up to 100 million so it would be a good start.

The algorithm on the page also takes a couple shortcuts (odd numbers and only checks up to the square root) which makes it extremely efficient and it will allow you to calculate long numbers.

Joe Meyer
  • 4,315
  • 20
  • 28
1

To be quite frank, some of the suggested solutions are really slow, and therefore are bad suggestions. For testing a single number to be prime you need some dividing/modulo operator, but for calculating a range you don't have to.

Basically you just exclude numbers that are multiples of earlier found primes, as the are (by definition) not primes themselves.

I will not give the full implementation, as that would be to easy, this is the approach in pseudo code. (On my machine, the actual implementation calculates all primes in an Sytem.Int32 (2 bilion) within 8 seconds.

public IEnumerable<long> GetPrimes(long max)
{
    // we safe the result set in an array of bytes.
    var buffer = new byte[long >> 4];
    // 1 is not a prime.
    buffer[0] = 1;

    var iMax = (long)Math.Sqrt(max);

    for(long i = 3; i <= iMax; i +=2 )
    {
        // find the index in the buffer
        var index = i >> 4;
        // find the bit of the buffer.
        var bit = (i >> 1) & 7;

        // A not set bit means: prime
        if((buffer[index] & (1 << bit)) == 0)
        {
            var step = i << 2;
            while(step < max)
            {
                // find position in the buffer to write bits that represent number that are not prime.
            }
        }
        // 2 is not in the buffer.
        yield return 2;

        // loop through buffer and yield return odd primes too.
    }
}

The solution requires a good understanding of bitwise operations. But it ways, and ways faster. You also can safe the result of the outcome on disc, if you need them for later use. The result of 17 * 10^9 numbers can be safed with 1 GB, and the calculation of that result set takes about 2 minutes max.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Corniel Nobel
  • 421
  • 4
  • 12
1

I know this is quiet old question, but after reading here: Sieve of Eratosthenes Wiki

This is the way i wrote it from understanding the algorithm:

void SieveOfEratosthenes(int n)
{
    bool[] primes = new bool[n + 1];

    for (int i = 0; i < n; i++)
        primes[i] = true;

    for (int i = 2; i * i <= n; i++)
        if (primes[i])
            for (int j = i * 2; j <= n; j += i)
                primes[j] = false;

    for (int i = 2; i <= n; i++)
        if (primes[i]) Console.Write(i + " ");
}

In the first loop we fill the array of booleans with true.

Second for loop will start from 2 since 1 is not a prime number and will check if prime number is still not changed and then assign false to the index of j.

last loop we just printing when it is prime.

0

Very similar - from an exercise to implement Sieve of Eratosthenes in C#:

public class PrimeFinder
{
    readonly List<long> _primes = new List<long>();

    public PrimeFinder(long seed)
    {
        CalcPrimes(seed);
    }

    public List<long> Primes { get { return _primes; } }

    private void CalcPrimes(long maxValue)
    {
        for (int checkValue = 3; checkValue <= maxValue; checkValue += 2)
        {
            if (IsPrime(checkValue))
            {
                _primes.Add(checkValue);
            }
        }
    }

    private bool IsPrime(long checkValue)
    {
        bool isPrime = true;

        foreach (long prime in _primes)
        {
            if ((checkValue % prime) == 0 && prime <= Math.Sqrt(checkValue))
            {
                isPrime = false;
                break;
            }
        }
        return isPrime;
    }
}
Gordon Mackie JoanMiro
  • 3,499
  • 3
  • 34
  • 42
0

U can use the normal prime number concept must only two factors (one and itself). So do like this,easy way

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PrimeNUmber
{
    class Program
    {
        static void FindPrimeNumber(long num)
        {
            for (long i = 1; i <= num; i++)
            {
                int totalFactors = 0;
                for (int j = 1; j <= i; j++)
                {
                    if (i % j == 0)
                    {
                        totalFactors = totalFactors + 1;
                    }
                }
                if (totalFactors == 2)
                {
                    Console.WriteLine(i);
                }
            }
        }

        static void Main(string[] args)
        {
            long num;
            Console.WriteLine("Enter any value");
            num = Convert.ToInt64(Console.ReadLine());
            FindPrimeNumber(num);
            Console.ReadLine();
        }
    }
}
Toto
  • 89,455
  • 62
  • 89
  • 125
user1134478
  • 21
  • 1
  • 1
  • 6
0

This is the fastest way to calculate prime numbers in C#.

   void PrimeNumber(long number)
    {
        bool IsprimeNumber = true;
        long  value = Convert.ToInt32(Math.Sqrt(number));
        if (number % 2 == 0)
        {
            IsprimeNumber = false;
        }
        for (long i = 3; i <= value; i=i+2)
        {             
           if (number % i == 0)
            {

               // MessageBox.Show("It is divisible by" + i);
                IsprimeNumber = false;
                break;
            }

        }
        if (IsprimeNumber)
        {
            MessageBox.Show("Yes Prime Number");
        }
        else
        {
            MessageBox.Show("No It is not a Prime NUmber");
        }
    }
rogerdeuce
  • 1,471
  • 6
  • 31
  • 48
Raj
  • 1
  • 3
  • Fastest way to calculate primes in C# – Raj Jul 24 '15 at 07:10
  • 2
    Please put some text or comments in answer to explain your answer. Adding just code will not help the person who asked question. Atleast explain your logic – Abhinav Singh Maurya Jul 24 '15 at 07:10
  • It's also not the fastest way. Glancing at it, if I call `PrimeNumber` with an even number, e.g. `PrimeNumber(1000000000000000000)`, it will calculate the square root, and do the loop even though it knows straight away it's not prime! (n.b. 1000000000000000000 is less than [`Int64.MaxValue`](https://msdn.microsoft.com/en-us/library/system.int64.maxvalue%28v=vs.110%29.aspx)). It'll then run the loop over odd numbers from 3 up to the square root, 1000000000 - which is very inefficient and pointless since we already know it's not prime. – Wai Ha Lee Jan 26 '16 at 09:57
  • BTW, somebody [flagged your question](http://stackoverflow.com/review/low-quality-posts/11021609) because they thought it was low quality. My "looks okay" was based on it being an attempt to answer the question, but doesn't mean it's a *good* answer. – Wai Ha Lee Jan 26 '16 at 10:04
0

This solution displays all prime numbers between 0 and 100.

        int counter = 0;
        for (int c = 0; c <= 100; c++)
        {
            counter = 0;
            for (int i = 1; i <= c; i++)
            {
                if (c % i == 0)
                { counter++; }
            }
            if (counter == 2)
            { Console.Write(c + " "); }
        }
rogerdeuce
  • 1,471
  • 6
  • 31
  • 48
Arthur
  • 1
  • 2
0
class CheckIfPrime
   {
    static void Main()
      {
          while (true)
        {
            Console.Write("Enter a number: ");
            decimal a = decimal.Parse(Console.ReadLine());
            decimal[] k = new decimal[int.Parse(a.ToString())];
            decimal p = 0;
            for (int i = 2; i < a; i++)
            {
                if (a % i != 0)
                {
                    p += i;
                    k[i] = i;
                }
                else
                    p += i;
            }
            if (p == k.Sum())
               { Console.WriteLine ("{0} is prime!", a);}
            else
               {Console.WriteLine("{0} is NOT prime", a);}

        }
    }

}
samets
  • 41
  • 5
0

There are some very optimal ways to implement the algorithm. But if you don't know much about maths and you simply follow the definition of prime as the requirement: a number that is only divisible by 1 and by itself (and nothing else), here's a simple to understand code for positive numbers.

public bool IsPrime(int candidateNumber)
{
    int fromNumber = 2;
    int toNumber = candidateNumber - 1;

    while(fromNumber <= toNumber)
    {
        bool isDivisible = candidateNumber % fromNumber == 0;
        if (isDivisible)
        {
            return false;
        }

        fromNumber++;
    }
    return true;
}

Since every number is divisible by 1 and by itself, we start checking from 2 onwards until the number immediately before itself. That's the basic reasoning.

diegosasw
  • 13,734
  • 16
  • 95
  • 159
0

You can do also this:

class Program
  {
    static void Main(string[] args)
    {
      long numberToTest = 350124;
      bool isPrime = NumberIsPrime(numberToTest);
      Console.WriteLine(string.Format("Number {0} is prime? {1}", numberToTest, isPrime));
      Console.ReadLine();
    }

    private static bool NumberIsPrime(long n)
    {
      bool retVal = true;

      if (n <= 3)
      {
        retVal = n > 1;
      } else if (n % 2 == 0 || n % 3 == 0)
      {
        retVal = false;
      }

      int i = 5;

      while (i * i <= n)
      {
        if (n % i == 0 || n % (i + 2) == 0)
        {
          retVal = false;
        }
        i += 6;
      }

      return retVal;
    }
  }
Dave
  • 1,912
  • 4
  • 16
  • 34
0

An easier approach , what i did is check if a number have exactly two division factors which is the essence of prime numbers .

    List<int> factorList = new List<int>();
    int[] numArray = new int[] { 1, 0, 6, 9, 7, 5, 3, 6, 0, 8, 1 };

    foreach (int item in numArray)
    {

        for (int x = 1; x <= item; x++)
        {
          //check for the remainder after dividing for each number less that number
            if (item % x == 0)
            {
                factorList.Add(x);
            }
        }
        if (factorList.Count == 2) // has only 2 division factors ; prime number
        {
            Console.WriteLine(item + " is a prime number ");
        }
        else
        {Console.WriteLine(item + " is not a prime number ");}

        factorList = new List<int>(); // reinitialize list
    }
Will Ness
  • 70,110
  • 9
  • 98
  • 181
Wesam
  • 932
  • 3
  • 15
  • 27
0

Here is a solution with unit test:

The solution:

public class PrimeNumbersKata
    {
        public int CountPrimeNumbers(int n)
        {
            if (n < 0) throw new ArgumentException("Not valide numbre");
            if (n == 0 || n == 1) return 0;
            int cpt = 0;
            for (int i = 2; i <= n; i++)
            {
                if (IsPrimaire(i)) cpt++;
            }
            return cpt;
        }

        private bool IsPrimaire(int number)
        {

            for (int i = 2; i <= number / 2; i++)
            {
                if (number % i == 0) return false;
            }
            return true;
        }
    }

The tests:

[TestFixture]
    class PrimeNumbersKataTest
    {
        private PrimeNumbersKata primeNumbersKata;
        [SetUp]
        public void Init()
        {
            primeNumbersKata = new PrimeNumbersKata();
        }
        [TestCase(1,0)]
        [TestCase(0,0)]
        [TestCase(2,1)]
        [TestCase(3,2)]
        [TestCase(5,3)]
        [TestCase(7,4)]
        [TestCase(9,4)]
        [TestCase(11,5)]
        [TestCase(13,6)]
        public void CountPrimeNumbers_N_AsArgument_returnCountPrimes(int n, int expected)
        {
            //arrange
            //act
            var actual = primeNumbersKata.CountPrimeNumbers(n);
            //assert
            Assert.AreEqual(expected,actual);
        }

        [Test]
        public void CountPrimairs_N_IsNegative_RaiseAnException()
        {
            var ex = Assert.Throws<ArgumentException>(()=> { primeNumbersKata.CountPrimeNumbers(-1); });
            //Assert.That(ex.Message == "Not valide numbre");
             Assert.That(ex.Message, Is.EqualTo("Not valide numbre"));

        }
    }
ilyes
  • 382
  • 2
  • 10
0

in the university it was necessary to count prime numbers up to 10,000 did so, the teacher was a little surprised, but I passed the test. Lang c#

void Main()
{
    int number=1;
    for(long i=2;i<10000;i++)
    {
        if(PrimeTest(i))
        {
            Console.WriteLine(number+++" " +i);
        }
    }
}

List<long> KnownPrime = new List<long>();
private bool PrimeTest(long i)
{
    if (i == 1) return false;
    if (i == 2)
    {
        KnownPrime.Add(i);
        return true;
    }
    foreach(int k in KnownPrime)
    {
        if(i%k==0)
            return false;
    }
    KnownPrime.Add(i);
    return true;
}
0
for (int i = 2; i < 100; i++)
{
    bool isPrimeNumber = true;
    for (int j = 2; j <= i && j <= 100; j++)
    {
        if (i != j && i % j == 0)
        {
            isPrimeNumber = false; break;
        }
    }
    if (isPrimeNumber)
    {
        Console.WriteLine(i);
    }
}
CinCout
  • 9,486
  • 12
  • 49
  • 67
Sudhar P
  • 11
  • 1
0

Prime Helper very fast calculation

public static class PrimeHelper
{

    public static IEnumerable<Int32> FindPrimes(Int32 maxNumber)
    {
        return (new PrimesInt32(maxNumber));
    }

    public static IEnumerable<Int32> FindPrimes(Int32 minNumber, Int32 maxNumber)
    {
        return FindPrimes(maxNumber).Where(pn => pn >= minNumber);
    }

    public static bool IsPrime(this Int64 number)
    {
        if (number < 2)
            return false;
        else if (number < 4 )
            return true;

        var limit = (Int32)System.Math.Sqrt(number) + 1;
        var foundPrimes = new PrimesInt32(limit);

        return !foundPrimes.IsDivisible(number);
    }

    public static bool IsPrime(this Int32 number)
    {
        return IsPrime(Convert.ToInt64(number));
    }

    public static bool IsPrime(this Int16 number)
    {
        return IsPrime(Convert.ToInt64(number));
    }

    public static bool IsPrime(this byte number)
    {
        return IsPrime(Convert.ToInt64(number));
    }
}

public class PrimesInt32 : IEnumerable<Int32>
{
    private Int32 limit;
    private BitArray numbers;

    public PrimesInt32(Int32 limit)
    {
        if (limit < 2)
            throw new Exception("Prime numbers not found.");

        startTime = DateTime.Now;
        calculateTime = startTime - startTime;
        this.limit = limit;
        try { findPrimes(); } catch{/*Overflows or Out of Memory*/}

        calculateTime = DateTime.Now - startTime;
    }

    private void findPrimes()
    {
        /*
        The Sieve Algorithm
        http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
        */
        numbers = new BitArray(limit, true);
        for (Int32 i = 2; i < limit; i++)
            if (numbers[i])
                for (Int32 j = i * 2; j < limit; j += i)
                     numbers[j] = false;
    }

    public IEnumerator<Int32> GetEnumerator()
    {
        for (Int32 i = 2; i < 3; i++)
            if (numbers[i])
                yield return i;
        if (limit > 2)
            for (Int32 i = 3; i < limit; i += 2)
                if (numbers[i])
                    yield return i;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    // Extended for Int64
    public bool IsDivisible(Int64 number)
    {
        var sqrt = System.Math.Sqrt(number);
        foreach (var prime in this)
        {
            if (prime > sqrt)
                break;
            if (number % prime == 0)
            {
                DivisibleBy = prime;
                return true;
            }
        }
        return false;
    }

    private static DateTime startTime;
    private static TimeSpan calculateTime;
    public static TimeSpan CalculateTime { get { return calculateTime; } }
    public Int32 DivisibleBy { get; set; }
}
0
    public static void Main()
    {  
        Console.WriteLine("enter the number");
        int i = int.Parse(Console.ReadLine());

        for (int j = 2; j <= i; j++)
        {
            for (int k = 2; k <= i; k++)
            {
                if (j == k)
                {
                    Console.WriteLine("{0}is prime", j);

                    break;
                }
                else if (j % k == 0)
                {
                    break;
                }
            }
        }
        Console.ReadLine();          
    }
Edwin de Koning
  • 14,209
  • 7
  • 56
  • 74
0
static void Main(string[] args)
    {  int i,j;
        Console.WriteLine("prime no between 1 to 100");
    for (i = 2; i <= 100; i++)
    {
        int count = 0;
        for (j = 1; j <= i; j++)
        {

            if (i % j == 0)
            { count=count+1; }
        }

        if ( count <= 2)
        { Console.WriteLine(i); }


    }
    Console.ReadKey();

    }
animuson
  • 53,861
  • 28
  • 137
  • 147