2010-07-19 3 views
1

Я пытаюсь написать функцию числа чисел в C#, и мне интересно, будет ли работать следующий код. Он «появляется» для работы с первыми 50 номерами или около того. Я просто хочу убедиться, что он будет работать независимо от того, насколько велика цифра:Prime Number Formula

static bool IsPrime(int number) 
{ 
    if ((number == 2) || (number == 3) || (number == 5) || (number == 7) || (number == 9)) 
      return true; 

    if ((number % 2 != 0) && (number % 3 != 0) && (number % 5 != 0) && 
     (number % 7 != 0) && (number % 9 != 0) && (number % 4 != 0) && 
     (number % 6 != 0)) 
     return true; 

     return false; 
} 
+8

Почему бы просто не использовать% 2? 9, вероятно, [ошибка эксперимента] (http://www.workjoke.com/mathematicians-jokes.html). –

+31

Глядя на свою репутацию, вопросы и ответы - вы здесь шутите? ;) –

+0

Не обязательно, потому что любое простое число, большее 10, также необходимо проверить (например, 121 = 11 * 11 из принятого ответа). Кроме того, нет необходимости проверять '% 6', так как он кратен«% 2 »и'% 9', так как он кратен «% 3». – iliketocode

ответ

29

Нет, это не сработает! Попробуйте, например, 121 = 11 * 11, который, очевидно, не является простым.

Для любого номера, присвоенного вашей функции, то есть произведение простых чисел X1, X2, ..., Xn (где п> = 2) со всеми их быть больше или равно 11, ваша функция возвращает истину. (А также, как уже говорилось, 9 не является простым).

Из википедии вы можете увидеть, что:

В математике, простое число (или простое) натуральное число, которое имеет ровно два различных делителей натурального числа: 1 и самого себя.

так очень простой и наивный алгоритм на проверки, является ли число простым может быть:

public bool CalcIsPrime(int number) { 

    if (number == 1) return false; 
    if (number == 2) return true; 

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

    for (int i = 2; i < number; i++) { // Advance from two to include correct calculation for '4' 
     if (number % i == 0) return false; 
    } 

    return true; 

} 

Для более совершенных алгоритмов проверки здесь: Primality Test

Если вы хотите проверить свой код, сделать inlcude a тест, вот тестовый пример, написанный в xunit.

 [Theory] 
     [MemberData(nameof(PrimeNumberTestData))] 
     public void CalcIsPrimeTest(int number, bool expected) { 
      Assert.Equal(expected, CalcIsPrime(number)); 
     } 

     public static IEnumerable<object[]> PrimeNumberTestData() { 
      yield return new object[] { 0, false }; 
      yield return new object[] { 1, false }; 
      yield return new object[] { 2, true }; 
      yield return new object[] { 3, true }; 
      yield return new object[] { 4, false }; 
      yield return new object[] { 5, true }; 
      yield return new object[] { 6, false }; 
      yield return new object[] { 7, true }; 
      yield return new object[] { 8, false }; 
      yield return new object[] { 9, false }; 
      yield return new object[] { 10, false }; 
      yield return new object[] { 11, true }; 
      yield return new object[] { 23, true }; 
      yield return new object[] { 31, true }; 
      yield return new object[] { 571, true }; 
      yield return new object[] { 853, true }; 
      yield return new object[] { 854, false }; 
      yield return new object[] { 997, true }; 
      yield return new object[] { 999, false }; 
     } 
+10

> «Если было так легко проверить, было ли число простым, то я думаю, что RSA не будет настолько безопасным» На самом деле, безопасность RSA зависит от того, что она _easy_, чтобы определить, является ли число простым (это делает безопасный ключ возможно генерация) и _hard_ для того, чтобы он обрабатывал произведение двух простых чисел (это делает шифрование безопасным). – avalys

+6

Необходимо только проверить до Math.sqrt (number) – Malfist

+0

Спасибо за ваш комментарий, вы правы. Я удалил его. – 2010-07-19 23:36:53

3

Такой подход, безусловно, не будет работать, если не ваш, если заявление явно перечисляет все простые числа от 0 до SQRT (INT_MAX) (или эквивалент # C).

Для правильной проверки подлинности вам необходимо попытаться разделить число на каждое простое число меньше его квадратного корня. Алгоритм Sieve of Eratosthenes - ваш лучший выбор.

+0

int.MaxValue дает C# max для int. –

+0

Нет, вам нужно только проверить квадратный корень. – starblue

+0

@starblue: для любого конкретного номера вам нужно проверить его квадратный корень (как я сказал в своем ответе).Для того, чтобы общая функция работала для ВСЕХ возможных входов, ей пришлось бы кодировать все простые числа вплоть до квадратного корня из максимально возможного ввода. Очевидно, если бы вы действительно собирались написать это так (не надо !!!), вам понадобится короткое замыкание. Возможно, с помощью обратного оператора switch с провалом, если вы делали это в C. Better, просто чтобы использовать какой-то массив, хотя ... –

2

Вы, по-видимому, пишете из контрафактного измерения, где 9 - простое число, поэтому я думаю, что наши ответы могут не сработать для вас. Две вещи, хотя: (! Номер% 2 = 0)

  1. простое число, порождающие функции нетривиальным, но выход материи, страница Wikipedia является хорошим стартер (http://en.wikipedia.org/wiki/Formula_for_primes)

  2. из него вытекает (номер% 4! = 0). Если вы не можете разделить на 10, то вы также не можете делить на 100.

10

Это должно было быть сделано ...

public static bool IsPrime(this int number) 
{ 
    return (Enumerable.Range(1,number).Where(x => number % x == 0).Count() == 2); 
} 
+3

return (Enumerable.Range (1, number) .Count (x => number% x == 0) == 2); – YesMan85

+1

Linq намного медленнее, чем версия метода. Я просто протестировал его в миллисекундах: 18: 162 для истины и 29: 1387 для ложных чисел 1-10 000. Но да, надо хотя бы показать, как это делается :) Я не уверен, почему истина быстрее. Метод, который я использую, практически идентичен тому, который указан в принятом ответе. Во всяком случае, так много для интересной траты времени. Это может быть что-то со скоростью, которую она вычисляет. Он не получит его, если он меньше миллисекунды. Но linq - это то же самое. Интересно. –

+1

На самом деле, мой код метода вычисляет только до sqrt. Это может изменить ситуацию. ** И это было так. ** Как только я исправил это, есть небольшая разница. 14:24 и 10:35. –

1

простоты тестирования путь, но в случае, если вы хотите быстро и грязный хак, вот что-то.

Если это не работает достаточно быстро, вы можете создать класс вокруг него и сохранить коллекцию PrimeNumbers от вызова к вызову, вместо того, чтобы переустанавливать его для каждого вызова.

public bool IsPrime(int val) 
    { 
     Collection<int> PrimeNumbers = new Collection<int>(); 
     int CheckNumber = 5; 
     bool divisible = true; 
     PrimeNumbers.Add(2); 
     PrimeNumbers.Add(3); 

     // Populating the Prime Number Collection 
     while (CheckNumber < val) 
     { 
      foreach (int i in PrimeNumbers) 
      { 
       if (CheckNumber % i == 0) 
       { 
        divisible = false; 
        break; 
       } 
       if (i * i > CheckNumber) { break; } 
      } 
      if (divisible == true) { PrimeNumbers.Add(CheckNumber); } 
      else { divisible = true; } 
      CheckNumber += 2; 
     } 
     foreach (int i in PrimeNumbers) 
     { 
      if (CheckNumber % i == 0) 
      { 
       divisible = false; 
       break; 
      } 
      if (i * i > CheckNumber) { break; } 
     } 
     if (divisible == true) { PrimeNumbers.Add(CheckNumber); } 
     else { divisible = true; } 

     // Use the Prime Number Collection to determine if val is prime 
     foreach (int i in PrimeNumbers) 
     { 
      if (val % i == 0) { return false; } 
      if (i * i > val) { return true; } 
     } 
     // Shouldn't ever get here, but needed to build properly. 
     return true; 
    } 
1

Есть несколько основных правил, которые вы можете следовать, чтобы проверить, является ли число премьер

  1. Даже цифры из. Если x% 2 = 0, то оно не является простым
  2. Все непустые числа имеют простые множители. Поэтому вам нужно всего лишь проверить число против простых чисел, чтобы выяснить, не является ли оно фактором
  3. Максимально возможный коэффициент, который имеет любой номер, является его квадратным корнем. Вам нужно только проверить, являются ли значения < = sqrt (number_to_check) даже делимыми.

Используя этот набор логики, следующая формула вычисляет 1 000 000 простых чисел, генерируемых в: 134.4164416 сек. На C# в одном потоке.

public IEnumerable<long> GetPrimes(int numberPrimes) 
    { 
     List<long> primes = new List<long> { 1, 2, 3 }; 
     long startTest = 3; 

     while (primes.Count() < numberPrimes) 
     { 
     startTest += 2; 
     bool prime = true; 
     for (int pos = 2; pos < primes.Count() && primes[pos] <= Math.Sqrt(startTest); pos++) 
     { 
      if (startTest % primes[pos] == 0) 
      { 
      prime = false; 
      } 
     } 
     if (prime) 
      primes.Add(startTest); 
     } 
     return primes; 
    } 

Помните, что в алгоритме есть много возможностей для оптимизации. Например, алгоритм может быть распараллелен. Если у вас есть простое число (скажем, 51), вы можете проверить все числа до его квадрата (2601) для грубости в отдельных потоках, поскольку все возможные основные факторы хранятся в списке.

1

это простые один

только нечетные числа являются простыми .... так

static bool IsPrime(int number) 
{ 
int i; 
if(number==2) 
    return true;     //if number is 2 then it will return prime 
for(i=3,i<number/2;i=i+2)   //i<number/2 since a number cannot be 
    {          //divided by more then its half 
    if(number%i==0)     //if number is divisible by i, then its not a prime 
      return false; 
    } 
return true;      //the code will only reach here if control 
}          //is not returned false in the for loop 
+5

Каков результат 'IsPrime (4)'? – Thomash

1
static List<long> PrimeNumbers = new List<long>(); 

    static void Main(string[] args) 
    { 
     PrimeNumbers.Add(2); 
     PrimeNumbers.Add(3); 
     PrimeNumbers.Add(5); 
     PrimeNumbers.Add(7); 
     for (long i = 11; i < 10000000; i += 2) 
     { 
      if (i % 5 != 0) 
       if (IsPrime(i)) 
        PrimeNumbers.Add(i); 
     } 
    } 

    static bool IsPrime(long number) 
    { 
     foreach (long i in PrimeNumbers) 
     { 
      if (i <= Math.Sqrt(number)) 
      { 
       if (number % i == 0) 
        return false; 
      } 
      else 
       break; 
     } 
     return true; 
    } 
0

ExchangeCore Forums имеет хорошую битый код, который будет в значительной степени позволит вам генерировать любое количество ULong для простых чисел. Но в основном здесь суть:

int primesToFind = 1000; 
int[] primes = new int[primesToFind]; 
int primesFound = 1; 
primes[0] = 2; 
for(int i = 3; i < int.MaxValue() && primesFound < primesToFind; i++) 
{ 
    bool isPrime = true; 
    double sqrt = Math.sqrt(i); 
    for(int j = 0; j<primesFound && primes[j] <= sqrt; j++) 
    { 
     if(i%primes[j] == 0) 
     { 
     isPrime = false; 
     break; 
     } 
    } 
    if(isPrime) 
     primes[primesFound++] = i; 
} 

После того, как этот код закончит показ простых чисел будут все это можно найти в переменных штрихах массива.

1

Это простой код найти простое число зависит от вашего входа.

static void Main(string[] args) 
    { 
     String input = Console.ReadLine(); 
     long num = Convert.ToInt32(input); 
     long a, b, c; 
     c = 2; 
     for(long i=3; i<=num; i++){ 
      b = 0; 
      for (long j = 2; j < i ; j++) { 
       a = i % j; 
       if (a != 0) { 
        b = b+1; 
       } 
       else { 
        break; 
       } 
      } 

      if(b == i-2){ 
       Console.WriteLine("{0}",i); 
      } 
     } 
     Console.ReadLine(); 
    } 
0

Prime Числа от 0 - 1 миллион меньше, чем за две десятых секунды

Только что закончил его. Последний тест составлял 0,017 секунды.

Обычный ноутбук HP. 2,1 ГГц

Это занимает больше времени, когда оно становится больше. Для простых чисел 1 - 1 billion, мой последний тест был 28.6897 секунд. Это может быть быстрее в вашей программе, потому что я запускал объекты класса, чтобы получить значения параметров в моем.

Метод Info

  • Использует Решето Эратосфена
  • Принимает пол и потолок в качестве аргументов
  • используют массивы вместо списков для быстрого выполнения
  • Размера массива инициализируются в соответствии с Россером -Schoenfeld верхняя граница
  • Пропускает кратные 2, 5 и 7 при назначении значений
  • Максимальный диапазон составляет от 0 до 2,147,483,646   (1 мин 44,499 сек)
  • прокомментирован

Использование

using System; 
using System.Diagnostics; 
using System.Collections; 

Метод

private static int[] GetPrimeArray(int floor, int ceiling) 
{ 
    // Validate arguments. 
    if (floor > int.MaxValue - 1) 
     throw new ArgumentException("Floor is too high. Max: 2,147,483,646"); 
    else if (ceiling > int.MaxValue - 1) 
     throw new ArgumentException("Ceiling is too high. Max: 2,147,483,646"); 
    else if (floor < 0) 
     throw new ArgumentException("Floor must be a positive integer."); 
    else if (ceiling < 0) 
     throw new ArgumentException("Ceiling must be a positve integer."); 
    else if (ceiling < floor) 
     throw new ArgumentException("Ceiling cannot be less than floor."); 

    // This region is only useful when testing performance. 
    #region Performance 

    Stopwatch sw = new Stopwatch(); 
    sw.Start(); 

    #endregion 

    // Variables: 
    int stoppingPoint = (int)Math.Sqrt(ceiling); 
    double rosserBound = (1.25506 * (ceiling + 1))/Math.Log(ceiling + 1, Math.E); 
    int[] primeArray = new int[(int)rosserBound]; 
    int primeIndex = 0; 
    int bitIndex = 4; 
    int innerIndex = 3; 

    // Handle single digit prime ranges. 
    if (ceiling < 11) 
    { 
     if (floor <= 2 && ceiling >= 2) // Range includes 2. 
      primeArray[primeIndex++] = 2; 

     if (floor <= 3 && ceiling >= 3) // Range includes 3. 
      primeArray[primeIndex++] = 3; 

     if (floor <= 5 && ceiling >= 5) // Range includes 5. 
      primeArray[primeIndex++] = 5; 

     return primeArray; 
    } 

    // Begin Sieve of Eratosthenes. All values initialized as true. 
    BitArray primeBits = new BitArray(ceiling + 1, true); 
    primeBits.Set(0, false); // Zero is not prime. 
    primeBits.Set(1, false); // One is not prime. 

    checked // Check overflow. 
    { 
     try 
     { 
      // Set even numbers, excluding 2, to false. 
      for (bitIndex = 4; bitIndex < ceiling; bitIndex += 2) 
       primeBits[bitIndex] = false; 
     } 
     catch { } // Break for() if overflow occurs. 
    } 

    // Iterate by steps of two in order to skip even values. 
    for (bitIndex = 3; bitIndex <= stoppingPoint; bitIndex += 2) 
    { 
     if (primeBits[bitIndex] == true) // Is prime. 
     { 
      // First position to unset is always the squared value. 
      innerIndex = bitIndex * bitIndex; 
      primeBits[innerIndex] = false; 

      checked // Check overflow. 
      { 
       try 
       { 
        // Set multiples of i, which are odd, to false. 
        innerIndex += bitIndex + bitIndex; 
        while (innerIndex <= ceiling) 
        { 
         primeBits[innerIndex] = false; 
         innerIndex += bitIndex + bitIndex; 
        } 
       } 
       catch { continue; } // Break while() if overflow occurs. 
      } 
     } 
    } 

    // Set initial array values. 
    if (floor <= 2) 
    { 
     // Range includes 2 - 5. 
     primeArray[primeIndex++] = 2; 
     primeArray[primeIndex++] = 3; 
     primeArray[primeIndex++] = 5; 
    } 

    else if (floor <= 3) 
    { 
     // Range includes 3 - 5. 
     primeArray[primeIndex++] = 3; 
     primeArray[primeIndex++] = 5; 
    } 
    else if (floor <= 5) 
    { 
     // Range includes 5. 
     primeArray[primeIndex++] = 5; 
    } 

    // Increment values that skip multiples of 2, 3, and 5. 
    int[] increment = { 6, 4, 2, 4, 2, 4, 6, 2 }; 
    int indexModulus = -1; 
    int moduloSkipAmount = (int)Math.Floor((double)(floor/30)); 

    // Set bit index to increment range which includes the floor. 
    bitIndex = moduloSkipAmount * 30 + 1; 

    // Increase bit and increment indicies until the floor is reached. 
    for (int i = 0; i < increment.Length; i++) 
    { 
     if (bitIndex >= floor) 
      break; // Floor reached. 

     // Increment, skipping multiples of 2, 3, and 5. 
     bitIndex += increment[++indexModulus]; 
    } 

    // Initialize values of return array. 
    while (bitIndex <= ceiling) 
    { 
     // Add bit index to prime array, if true. 
     if (primeBits[bitIndex]) 
      primeArray[primeIndex++] = bitIndex; 

     checked // Check overflow. 
     { 
      try 
      { 
       // Increment. Skip multiples of 2, 3, and 5. 
       indexModulus = ++indexModulus % 8; 
       bitIndex += increment[indexModulus]; 
      } 
      catch { break; } // Break if overflow occurs. 
     } 
    } 

    // Resize array. Rosser-Schoenfeld upper bound of π(x) is not an equality. 
    Array.Resize(ref primeArray, primeIndex); 

    // This region is only useful when testing performance. 
    #region Performance 

    sw.Stop(); 

    if (primeArray.Length == 0) 
     Console.WriteLine("There are no prime numbers between {0} and {1}", 
      floor, ceiling); 
    else 
    { 
     Console.WriteLine(Environment.NewLine); 
     for (int i = 0; i < primeArray.Length; i++) 
      Console.WriteLine("{0,10}:\t\t{1,15:#,###,###,###}", i + 1, primeArray[i]); 
    } 

    Console.WriteLine(); 
    Console.WriteLine("Calculation time:\t{0}", sw.Elapsed.ToString()); 

    #endregion 

    return primeArray; 
} 

Комментарии приветствуются! Особенно улучшения.

+0

Это не имеет особого отношения к исходному вопросу. – Teepeemm

+0

@Teepeemm: «Я пытаюсь написать функцию числа в C#». Функция выше - функция простого числа. Я не назвал его «IsPrime», но он делает то же самое. Чтобы узнать, является ли 951 простым, используйте GetPrimeArray (951, 951). Он пишет: «Нет простых чисел между 951 и 951.» –

0

Здесь мы должны учитывать фактор квадратного корня. Простое число может быть проверено, если оно не делится на любое число, меньшее квадратного корня из любого близкого числа.

static bool isPrime(long number) 
{ 
    if (number == 1) return false; 
    if (number == 2) return true; 
    if (number % 2 == 0) return false; //Even number  
    long nn= (long) Math.Abs(Math.Sqrt(number)); 
    for (long i = 3; i < nn; i += 2) { 
     if (number % i == 0) return false; 
    } 
    return true; 
}