Программирование на C — проверка простого числа

#c #loops #for-loop #primes #function-definition

#c #циклы #for-цикл #простые числа #функция-определение

Вопрос:

Я пытаюсь проверить, является ли данное число простым, но я столкнулся с проблемой. Это код:

 #include <stdio.h>
#include <math.h>
#include <stdbool.h>

bool isPrime(int input)
{
    for (int i = sqrt(input); i >= 2; i--)
    {
        if (input % i == 0)
        {
            return false;
        }
    return true; 
    }
    
}

int main()
{
    int input;
    scanf("%d", amp;input);
    
    if (isPrime(input))
    {
        printf("Is prime number");
    } else
    {
        printf("Is not prime number");
    }
    
    return 0;
}
  

В блоке кода моей isPrime функции, если я введу return true; цикл for, как указано выше, в некоторых случаях это будет неправильно (например, когда input равно 10, будет объявлено, что 10 является простым числом). Но если я помещаю return true; вне цикла for, он работает нормально. Так в чем же разница?

Комментарии:

1. return true; немедленно завершает функцию возвращаемым значением true . Поэтому, когда вы вводите 10, функция проверяет 10/3, а затем возвращает true .

2. Действительно, если вы возвращаете true только после проверки всех потенциальных делителей, а не после самого первого из них, он возвращает правильный результат, какой сюрприз.

3. Предупреждение компилятора: isPrime : не все пути управления возвращают значение . Пожалуйста, переместите return true to за пределы цикла. Предупреждения компилятора помогут вам.

4. Это не Python. Даже если вы не сделали отступ в return true; строке, это не значит, что его нет внутри блока цикла. В C отступ не имеет значения для компилятора.

Ответ №1:

Давайте пройдемся по вашему циклу:

 for (int i = sqrt(input); i >= 2; i--)
{
  

Если ввод равен 10 , то i начинается как 3 (помните, что при присвоении значения с плавающей запятой an int дробная часть отбрасывается). 3 больше или равно 2 , поэтому выполняется тело цикла.

     if (input % i == 0)
    {
  

Остаток от 10 деления на 3 не равен нулю, поэтому мы не вводим тело if инструкции.

         return false;
    }
return true; 
}
  

И затем мы немедленно возвращаемся true .

Из-за этого, независимо от того, какие входные данные вы предоставляете, ваш цикл будет повторяться только 1 раз. Если input равномерно делится на целое значение его квадратного корня (например , 9 , 16 , или 25 ), то выполняется тело if инструкции, и оно возвращает false , в противном случае оно возвращается безоговорочно true .

Чтобы ваша функция работала правильно, вы должны переместить return true; оператор за пределы тела цикла — вы должны возвращаться только true тогда, когда исчерпали все значения i между sqrt(input) и 2 .

Ответ №2:

Функция возвращает true, если первый делитель в цикле for не делит целевое число.

потому что этот оператор возврата

     return true; 
  

находится внутри цикла for .

 bool isPrime(int input)
{
    for (int i = sqrt(input); i >= 2; i--)
    {
        if (input % i == 0)
        {
            return false;
        }
    return true; 
    }
    
} 
  

Более того, функция имеет неопределенное поведение, если она вызывается, например, для простых чисел 2 или 3 или если в функцию передается неположительное число.

Размещение оператора return

 return true; 
  

вне цикла ваша функция не корректна.

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

Функция может быть записана следующим образом

 bool isPrime( unsigned long long n )
{
    bool prime = n % 2 == 0 ? n == 2 : n != 1;

    for ( unsigned long long int i = 3; prime amp;amp; i <= n / i; i  = 2 )
    {
        prime = n % i != 0;
    }

    return prime;  
} 
  

Функция может быть вызвана как

 unsigned int input;
scanf("%u", amp;input);

if (isPrime(input))
{
    printf("Is prime number");
} else
{
    printf("Is not prime number");
}
  

Ответ №3:

Когда вы помещаете return true; внутри цикла, этот оператор будет выполняться всякий раз, когда предыдущее if условие равно false . Вы хотите вернуться true только после завершения for цикла и отсутствия делителей. Вот почему return оператор должен быть вне цикла.

Ответ №4:

Это происходит потому, что ваш цикл for не завершен полным обходом i, но return true оператор сообщает коду выполнить его в самый первый раз, когда ваше условие if становится ложным, а затем выйти из цикла. Итак, представьте, что я даю вам 10 плиток шоколада и говорю вам откусить от каждой и собирать только темные. Ты откусываешь кусочек от первого, он сладкий, ты его убираешь. Вы откусываете второй кусочек, и он темный. Вы собираете его и говорите мне, что закончили, хотя на самом деле это не так (вы не проверили остальные шоколадные батончики, чтобы посмотреть, есть ли там больше темных или нет). Это то, что вы делаете в своем коде. Надеюсь, пример понятен и полезен 🙂