简体   繁体   中英

I have a problem of using sqrt function which is used in a C program

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

int main()
{
    int n, i, flag = 0;
    printf("Enter the number\n");
    scanf("%d", &n);
    for (i = 2; i <= sqrt(n); i++)
    {
        if (n % i == 0)
        {
            flag = 1;
            break;
        }
    }
    if (flag == 0)
    {
        printf("%d is a prime number", n);
    }
    else
    {
        printf("%d is not a prime number", n);
    }
    return 0;
}

In the for loop why is the sqrt function is used? Because for checking if the number n is a prime number, shouldn't we check till n ?

If n is evenly divisible by i , then both i and n/i are divisors. If i is greater than sqrt(n) , then n/i is smaller than sqrt(n) , ie: for any divisor i > sqrt(n) there is a divisor j < sqrt(n) . If sqrt(n) is an integer, then it is a divisor of n .

Hence it suffices to test integers up to and including sqrt(n) .

Note these issues:

  • computing sqrt(n) at each iteration is wasteful and the compiler might not be smart enough to determine that the result is the same because n does not change. Computing the upper bound before the loop is advisable.

  • on CPUs without fast floating point arithmetics, using a different test may be more efficient such as i * i <= n or n / i >= i .

  • the program reports 0 and 1 as prime numbers.

  • if the user enters a negative number, sqrt(n) returns NaN , conversion to int is undefined and may produce 0 , hence the test will fail and the number will be reported as prime.

  • if the user types anything that is not a number, the behavior is undefined because scanf() will fail and n will remain uninitialized. You should test the return value of scan() , which will be 1 for a successful conversion and 0 for invalid input or EOF for end of file.

Here is a modified version:

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

int main() {
    int n, sq, i, flag = 0;

    printf("Enter the number: ");
    if (scanf("%d", &n) != 1) {
        printf("invalid input\n");
        return 1;
    }
    if (i < 2) {
        /* reject 0, 1 and negative numbers */
        flag = 1;
    } else {
        sq = round(sqrt(n));
        for (i = 2; i <= sq; i++) {
            if (n % i == 0) {
                flag = 1;
                break;
            }
        }
    }
    if (flag == 0) {
        printf("%d is a prime number\n", n);
    } else {
        printf("%d is not a prime number\n", n);
    }
    return 0;
}

If a number is not a prime a prime factor of it will always be less than or equal to its square root. This is why we only check factors up to a number's square root.

Consider checking the number 59 . Its square root is (approximately) 7.68 . If we're incrementing up from 2 , we will only have to iterate from 2 to 7 to determine if this is a prime number, rather than from 2 to 59 (or rather 58 ). This saves our loop many iterations.

Consider how that impacts a number like 7481 . We can iterate from 2 to 86 rather than from 2 to 7480 to find out that it's prime.

As the number you're checking gets bigger, this saves more and more computing time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM