Check If a Number Is Prime in Python: Fast and Clear Methods

Quick answer: To check whether a number is prime, reject values below two, then test divisors from two through math.isqrt(n). If a divisor divides evenly, the number is composite; if none does, it is prime. Checking only through the square root is sufficient because every factor pair has at least one factor no larger than the square root. For many values up to a fixed limit, use a sieve instead.

Python Pool infographic showing prime checks, divisors up to square root, edge cases, and a sieve
A number greater than one is prime when no integer up to its square root divides it; for many queries, a sieve reuses the work across a range.

A prime number is an integer greater than 1 with exactly two positive divisors: 1 and itself. In Python, the usual beginner-friendly approach is trial division: try possible divisors and stop as soon as one divides evenly. Primality asks whether a number has a divisor, while Prime Factorization in Python Guide records every prime divisor and its multiplicity.

You do not need to test every number up to n - 1. If a number has a factor larger than its square root, it also has a matching factor smaller than its square root. That means checking divisors up to math.isqrt(n) is enough.

The official Python documentation for math.isqrt() is useful for the square-root limit.

Start with clear rules: 0 and 1 are not prime, negative numbers are not prime, 2 is prime, and any even number larger than 2 is not prime. Handling those cases early makes the main loop smaller and easier to read.

For small classroom examples, a simple loop is fine. For cryptography or very large integers, use a library designed for number theory instead of a basic trial-division function.

Prime checking is a good example of improving an algorithm without making it hard to read. The first version can test every possible divisor. The improved version stops at the square root. The faster version skips even divisors after handling 2. Each step keeps the same result while reducing unnecessary work.

Keep the input type clear. These functions expect integers. If a value comes from a form, command line, file, or API response, parse it first and reject invalid text before calling the prime checker.

Also decide what your program should do with non-positive values. In most math and programming contexts, values below 2 simply return False. Raising an exception is usually only needed when negative input means the caller made a mistake.

The examples below keep the logic explicit so you can see each decision.

Check A Number With Trial Division

This direct version checks every possible divisor from 2 up to one less than the number.

number = 17
is_prime = number > 1

for divisor in range(2, number):
    if number % divisor == 0:
        is_prime = False
        break

print(is_prime)

The loop stops early if it finds a divisor. For 17, no divisor is found, so the result is True.

This version is easy to understand, but it does extra work for larger numbers.

Use this form when teaching the idea of divisibility. For real checks, move the logic into a function so the rules can be reused and tested.

Handle Small And Negative Numbers

Numbers less than 2 are not prime.

def is_prime_basic(number):
    if number < 2:
        return False
    for divisor in range(2, number):
        if number % divisor == 0:
            return False
    return True

print(is_prime_basic(-7))
print(is_prime_basic(1))
print(is_prime_basic(2))

This function returns early for values that cannot be prime. That makes the later loop responsible only for realistic candidates.

Early returns also make the function easier to audit. Each special case is handled once, and the main loop stays focused on divisibility.

Python Pool infographic showing an integer, divisors, one, two, and boundary cases
Prime definition: An integer, divisors, one, two, and boundary cases.

Use A Square-Root Limit

math.isqrt() returns the integer square root without floating-point rounding issues.

from math import isqrt

def is_prime(number):
    if number < 2:
        return False
    for divisor in range(2, isqrt(number) + 1):
        if number % divisor == 0:
            return False
    return True

print(is_prime(97))
print(is_prime(100))

This is much faster than checking all divisors up to the number for larger inputs.

The + 1 matters because range() stops before the end value.

For example, if the square root limit is 7, the loop must include 7 as a possible divisor. Without the extra one, that final divisor would be skipped.

Skip Even Divisors

After handling 2, every other even number can be rejected or skipped.

from math import isqrt

def is_prime_fast(number):
    if number < 2:
        return False
    if number == 2:
        return True
    if number % 2 == 0:
        return False
    for divisor in range(3, isqrt(number) + 1, 2):
        if number % divisor == 0:
            return False
    return True

print(is_prime_fast(29))
print(is_prime_fast(91))

This loop checks only odd divisors after rejecting even candidates. It is still simple, but it cuts the loop work roughly in half.

This version is a good practical default for ordinary scripts. It avoids unnecessary even checks without adding complex number-theory code.

Python Pool infographic showing a loop bound, remainder, square root, and early exit
Trial division: A loop bound, remainder, square root, and early exit.

List Primes In A Range

Reuse the prime-checking function to collect primes from a range.

from math import isqrt

def is_prime(number):
    if number < 2:
        return False
    for divisor in range(2, isqrt(number) + 1):
        if number % divisor == 0:
            return False
    return True

primes = [number for number in range(2, 20) if is_prime(number)]
print(primes)

This style is useful for small reports and learning exercises. For very large ranges, look into sieve algorithms.

A sieve is better when you need many primes up to a limit because it reuses work across the whole range. Calling a single-number test repeatedly is simpler, but not always the fastest approach.

Validate User Input

When the number comes from text input, parse and validate it before checking primality.

from math import isqrt

def is_prime(number):
    if number < 2:
        return False
    for divisor in range(2, isqrt(number) + 1):
        if number % divisor == 0:
            return False
    return True

text = "31"
number = int(text)

print(is_prime(number))

In a real program, catch ValueError if the input may not be an integer. Keep parsing errors separate from prime-checking logic.

Common mistakes include treating 1 as prime, forgetting to stop at the square-root limit, and using floating-point square roots when integer math is cleaner.

Another common mistake is returning too early from the loop. Only return True after all required divisors have been tested. Returning inside the first non-dividing case can mark composite numbers as prime by accident.

In short, handle values below 2 first, test divisibility only up to isqrt(n), skip even divisors when you want a small speed improvement, and keep user input parsing outside the prime-checking function.

Python Pool infographic showing a range, marked multiples, and repeated prime queries
Sieve choice: A range, marked multiples, and repeated prime queries.

Guard The Small Values

Zero, one, and negative integers are not prime. Keep this rule at the top of the function so the loop only handles candidates for which divisibility makes sense.

def is_prime_basic(number):
    if number < 2:
        return False
    for divisor in range(2, number):
        if number % divisor == 0:
            return False
    return True

print([number for number in range(12) if is_prime_basic(number)])

Stop At The Integer Square Root

math.isqrt returns the exact integer square root without floating-point rounding. Testing through that bound reduces trial divisions from n to approximately the square root of n.

from math import isqrt


def is_prime(number):
    if number < 2:
        return False
    for divisor in range(2, isqrt(number) + 1):
        if number % divisor == 0:
            return False
    return True

for candidate in (2, 3, 9, 17, 49):
    print(candidate, is_prime(candidate))
Python Pool infographic testing negative values, zero, large inputs, and edge cases
Prime checks: Negative values, zero, large inputs, and edge cases.

Skip Easy Composite Cases

After handling values below two, two is the only even prime. Checking two first and then testing odd divisors is a simple optimization that preserves the same proof.

from math import isqrt


def is_prime_fast(number):
    if number < 2:
        return False
    if number == 2:
        return True
    if number % 2 == 0:
        return False
    return all(number % divisor for divisor in range(3, isqrt(number) + 1, 2))

print(is_prime_fast(97))

Use A Sieve For Many Candidates

A sieve marks multiples of each prime and reuses that work for every value up to the limit. It uses memory proportional to the limit, so choose it for batches of queries rather than one very large isolated integer.

def primes_up_to(limit):
    flags = [True] * (limit + 1)
    if limit >= 0:
        flags[0] = False
    if limit >= 1:
        flags[1] = False
    for candidate in range(2, int(limit ** 0.5) + 1):
        if flags[candidate]:
            for multiple in range(candidate * candidate, limit + 1, candidate):
                flags[multiple] = False
    return [number for number, prime in enumerate(flags) if prime]

print(primes_up_to(30))

Python’s official math.isqrt() returns an integer square root, which is the correct bound for trial division. Related references include prime factorization, number predicates, and integer limits.

For related number algorithms, compare prime factorization, integer limits, and iteration patterns when scaling a prime test.

Frequently Asked Questions

What is the simplest prime check in Python?

Handle values below two, then test divisors from two through the integer square root and stop at the first exact division.

Why only check divisors up to the square root?

If a composite number has a factor larger than its square root, its matching factor is smaller than the square root.

Is one a prime number?

No. Prime numbers have exactly two positive divisors, while one has only itself.

How do I test many numbers efficiently?

Use a sieve of Eratosthenes when you need all primes up to a known limit instead of repeating trial division.

Subscribe
Notify of
guest
6 Comments
Oldest
Newest Most Voted
Sid
Sid
4 years ago

Methods 1 through 3 are all the same method. They are only slight variations to be selective about which numbers to iterate. How about adding a method that uses the Sieve of Eratosthenes, and one that uses a lookup table?

Python Pool
Admin
4 years ago
Reply to  Sid

Great catch! I’ll update the post with these methods.

Gabriel
Gabriel
4 years ago

Hi,

method 1.5 cannot work and should be updated :p

Cheers

Pratik Kinage
Admin
4 years ago
Reply to  Gabriel

Hi Gabriel,

Thank you for informing me :). I’ve updated the post accordingly.

Regards,
Pratik

ITech
ITech
4 years ago

I believe your purpose in the statement:
“int(num**1/2)”

is to refer to the root of num, but because you didn’t use parenthesis it becomes:
“int(num/2)”

if you do correct it to:
“int(num**0.5)”

the range needs to be changed in some of your codes here or else the range will be null for lower numbers, I checked for example with 3 and 5.

Pratik Kinage
Admin
4 years ago
Reply to  ITech

Correct. Thank you for pointing it out!