0

the following code works but for some numbers it needs a lot of time to say if the number is prime or not. What can i do to make it faster? Here is the code:

using System;
using System.Collections.Generic;
using System.Linq;``
using System.Text;
using System.Threading.Tasks;

namespace Exercise23
{
    class Exercise23
    {
        static void Main(string[] args)
        {
            long number = long.Parse(Console.ReadLine());
            if (IsPrime(number))
            {
                Console.WriteLine("True");
            }
            else
            {
                Console.WriteLine("False");
            }
        }
        public static bool IsPrime(long number)
        {
            if (number == 1) return false;
            if (number == 2) return true;
            //if (number == 6737626471) return true;

            if (number % 2 == 0) return false;    

            for (int i = 3; i < number; i += 2)
            {
                if (number % i == 0) return false;
            }
            return true;
        }
    }
}
CS.
  • 741
  • 9
  • 24
  • 1
    Some algorithms just take a long time depending on the inputs, and that's just the way it is. Think about the super computers that compute the many digits of pi which still take a lot of time. – rory.ap May 20 '16 at 14:45
  • 9
    This is one of the slowest algorithms for determining primeness. The first step to make this faster: you only have to iterate to the square root of `number` (higher values can't be divisors). – René Vogt May 20 '16 at 14:46
  • 4
    @RenéVogt - higher values can be divisors - but if there is one, you'll have already located at least one other divisor (by which the higher divisor can be multiplied to obtain the original number) E.g. sqrt(10) is 3.16. Are you going to claim that 5 isn't a divisor of 10? – Damien_The_Unbeliever May 20 '16 at 14:48
  • This is one of the most classic problem of math (particularly number theory) and computing... the solution can be very simple to very complex, and the performance is varying a lot. It is quite broad topic, so to say... – Ian May 20 '16 at 14:48
  • Probably *the* slowest way. There is no reason to check for numbers greater than`number/2`. – Panagiotis Kanavos May 20 '16 at 14:50
  • `IsPrime(-1)`? Do not forget about negative numbers – Dmitry Bychenko May 20 '16 at 14:50
  • 2
    @Damien_The_Unbeliever right, that's what I meant :) – René Vogt May 20 '16 at 14:52
  • 1
    If this code works as is and the desire is simply to make it faster, doesn't it belong on CodeReview? – Chris Dunaway May 20 '16 at 15:43

2 Answers2

3

An easiest improvement is to make the loop shorter. If number is not prime, it can be written as

  N = A * B 

Let A <= B; in the worst case (A == B) and so A <= sqrt(N).

  public static bool IsPrime(long number) {
    if (number <= 1)
      return false;
    else if (number % 2 == 0)
      return number == 2;

    long N = (long) (Math.Sqrt(number) + 0.5);

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

    return true;
  }

So you have O(sqrt(N)) algorithm instead of O(N). For real improvement (for big numbers) see

AKS test (primarily academic use)

https://en.wikipedia.org/wiki/AKS_primality_test

Rabin-Miller test

https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test

Dmitry Bychenko
  • 165,109
  • 17
  • 150
  • 199
2

Based on this answer: https://stackoverflow.com/a/26760082/4499267 a way to speed things up can be:

  • The algorithm can be improved further by observing that all primes are of the form 6k ± 1, with the exception of 2 and 3.
  • This is because all integers can be expressed as (6k + i) for some integer k and for i = −1, 0, 1, 2, 3, or 4; 2 divides (6k + 0), (6k + 2), (6k + 4); and 3 divides (6k + 3).
  • So a more efficient method is to test if n is divisible by 2 or 3, then to check through all the numbers of form 6k ± 1 ≤ √n.
  • This is 3 times as fast as testing all m up to √n.

Here's a C implementation

int IsPrime(unsigned int number) {
    if (number <= 3 && number > 1) 
        return 1;            // as 2 and 3 are prime
    else if (number == 1 || number%2==0 || number%3==0) 
        return 0;     // check if number is divisible by 2 or 3
    else {
        unsigned int i;
        for (i=5; i*i<=number; i+=6) {
            if (number % i == 0 || number%(i + 2) == 0) 
                return 0;
        }
        return 1; 
    }
}
Community
  • 1
  • 1
Phate01
  • 2,378
  • 1
  • 29
  • 53