@VDiger

Поиск простых больших чисел на C# BigInteger?

Доброго времени суток, господа)

Учусь на первом курсе на втором семестре, по алгоритмам появилась такая задача->подать более быстрый способ поиска простых чисел и сравнить его с тем что есть. Этот первоначальный поиск:
static bool IsPrime(BigInteger num)
    {
        modulo = 1;
        if (num < 2) return false;
        else if (num < 4) return true;
        else if (num % 2 == 0)
        {
            modulo++;
            return false;
        }
        else for (BigInteger u = 3; u < num / 2; u += 2)
            {
                if (num % u == 0)
                {
                    return false;
                }
                modulo++;
            }
        return true;
    }

вот мое решение
using System;
    using System.Numerics;
    using System.Diagnostics;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;


    namespace Project2._0
    {
        class Program
        {
            static long modulo;
            static long modulo1;
            static void Main(string[] args)
            {
                BigInteger[] Array = { 100913, 1009139, 10091401, 100914061 , 1009140611 , 10091406133, 100914061337, 1009140613399 };//

        Console.WriteLine("Test IsPrime");
        TestFirstAlgorytm(Array);
        Console.WriteLine("Test IsPrime2");
        TestSecondAlgorytm(Array);
    }
    static void TestFirstAlgorytm(BigInteger[] Array)
    {
        for (int i = 0; i <= 7; i++)
        {

            BigInteger num = Array[i];
            long StartingTime = Stopwatch.GetTimestamp();
            IsPrime(num);
            long EndingTime = Stopwatch.GetTimestamp();
            long ElapsedTime = EndingTime - StartingTime;
            double ElapsedSeconds = ElapsedTime * (1.0 / Stopwatch.Frequency);
            Console.WriteLine("Count:{0}\tTime:{1}    \tTest:{2}\tArray:{3}", modulo, ElapsedSeconds, IsPrime(num), Array[i]);
        }
    }
    static void TestSecondAlgorytm(BigInteger[] Array)
    {
        for (int i = 0; i <= 7; i++)
        {

            BigInteger num = Array[i];
            long StartingTime = Stopwatch.GetTimestamp();
            IsPrimeImproved(num);
            long EndingTime = Stopwatch.GetTimestamp();
            long ElapsedTime = EndingTime - StartingTime;
            double ElapsedSeconds = ElapsedTime * (1.0 / Stopwatch.Frequency);
            Console.WriteLine("Count:{0}\tTime:{1}    \tTest:{2}\tArray:{3}", modulo1, ElapsedSeconds, IsPrime(num), Array[i]);
        }
    }
    static bool IsPrime(BigInteger num)
    {
        modulo = 1;
        if (num < 2) return false;
        else if (num < 4) return true;
        else if (num % 2 == 0)
        {
            modulo++;
            return false;
        }
        else for (BigInteger u = 3; u < num / 2; u += 2)
            {
                if (num % u == 0)
                {
                    return false;
                }
                modulo++;
            }
        return true;
    }
   static bool IsPrimeImproved(BigInteger num)
         {
             modulo1 = 0;
            //       int _sqrt_int = (int)Math.Sqrt((double)num); //Целая часть от квадратного корня из d
            if (num < 2) return false;
            else if (num < 4) return true;
            else if (num % 2 == 0)
            {
                modulo++;
                return false;
            }
            else
                for (BigInteger i = 3; i*i <= num; i+=2)
             {
                 modulo1++;
                 if ((num % i) == 0) //Проверка: остаток от деления d/i==0?
                     return false;
             }

             return true;
         }
}
}

но есть проблема: Отдельно первый алгоритм работает, а в собранном виде
нет. Всем кто поможет и укажет на мои ошибки, буду очень благодарен!
  • Вопрос задан
  • 1262 просмотра
Пригласить эксперта
Ответы на вопрос 1
@tomatho
Слишком большие числа для таких алгоритмов. Эти алгоритмы слишком медленные.
Другими словами, мой ответ такой: Этот код работает, просто вам не хватит терпения дождаться его завершения.
Update: modulo, modulo1. Что в оригинальном алгоритме, что в итоге - несёт какую-то бессмыслицу.

Чтобы улучшить скорость, используйте вместо BigInteger обычный long.
Этот тип позволит поддерживать числа до 9223372036854775807.
А это число существенно больше тех чисел, которые можно проверить на простоту приведёнными выше алгоритмами, за разумное время.

Что касается скоростных тестов на простоту, то можете реализовать тест Рабина-Миллера.
Он сравнительно прост, и очень эффективен. Проблема его лишь в том, что он отвечает:
"Это число простое с вероятностью 99.9999%"
Зато вероятность эта может быть выбрана произвольно высоко.
Например, он может ошибаться в среднем в одном случае из миллиона.

Что касается точных проверок на простоту, такие реализовать сложнее.
И я не думаю что у вас стоит такая задача.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы