Recommended Free Tools
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
For one integer, reject every value below 2, then test divisors from 2 through math.isqrt(n). If any divisor divides evenly, the number is composite; if none does, it is prime. This is exact trial division and needs only Python’s standard library.
The standard-library solution
math.isqrt() returns the floor of an integer’s exact square root. It was added in Python 3.8 and avoids floating-point rounding at the loop boundary; see the Python math documentation.
from math import isqrt
def is_prime(n: int) -> bool:
if n < 2:
return False
for divisor in range(2, isqrt(n) + 1):
if n % divisor == 0:
return False
return True
The + 1 is intentional: Python’s range stops before its second argument. Adding one means an exact square root is tested as a possible divisor.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteExample calls
print(is_prime(2)) # True
print(is_prime(17)) # True
print(is_prime(18)) # False
print(is_prime(1)) # False
print(is_prime(-11)) # False
Why checking only to the square root works
A composite number can be written as a product of two positive factors. If both factors were greater than sqrt(n), their product would be greater than n. Therefore, every composite n has at least one factor at or below its square root. Finding no divisor in that interval proves that no non-trivial factor exists.
#1 Best Overall
For example, 91 is composite because 7 × 13 = 91, and 7 is below sqrt(91). Once a divisor is found, the function can return immediately instead of testing the remaining candidates.
Inputs and edge cases
Zero, one, and negative integers
Primality is defined for integers greater than 1. Consequently, 0, 1, and every negative integer return False. The guard runs before isqrt, which requires a nonnegative integer.
Two and other small values
2 is prime. For n == 2, range(2, isqrt(2) + 1) is empty, so the function reaches return True. The same logic handles 3 and other values whose square root is below 2.
Rank #2
Non-integer arguments
The annotation documents the intended input; it does not enforce it at runtime. A float can produce surprising results, and a string raises a type error during comparison or modulo. Validate or convert input at the boundary of your program:
raw = input("Integer: ")
try:
value = int(raw)
except ValueError:
print("Enter a whole number.")
else:
print(is_prime(value))
Python’s bool type is a subclass of int, so is_prime(True) treats True as 1 and returns False. If your API must reject booleans explicitly, add if isinstance(n, bool): raise TypeError(...) before the numeric checks.
How the algorithm behaves
| Approach | Best fit | Work and storage | Trade-off |
|---|---|---|---|
| Basic trial division | One or occasional integers | Tests candidates through isqrt(n); constant extra storage |
Simple and easy to audit, but repeats work for separate calls |
| Skip even candidates | Single checks where a small optimization is useful | Checks 2, then odd divisors only | Fewer modulo operations, with slightly more branching |
| Sieve of Eratosthenes | Many queries up to a known maximum | Precomputes and stores primality for the whole range | More setup and memory, but work is reused across queries |
No universal input-count or numeric-size crossover is established; choose according to whether you have one value or a bounded batch, and whether clarity or precomputation matters more.
A small optimization for repeated single checks
After checking 2, every remaining possible prime divisor is odd. This version preserves the same proof while skipping even candidates:
from math import isqrt
def is_prime_odd_only(n: int) -> bool:
if n < 2:
return False
if n == 2:
return True
if n % 2 == 0:
return False
for divisor in range(3, isqrt(n) + 1, 2):
if n % divisor == 0:
return False
return True
Keep the straightforward version when teaching, reviewing, or maintaining code; the optimization is optional rather than a different definition of primality.
Checking many numbers with a sieve
If you need every prime up to a known limit, a sieve marks composites once and lets later lookups run in constant time:
def primes_up_to(limit: int) -> list[int]:
if limit < 2:
return []
prime = [True] * (limit + 1)
prime[0] = prime[1] = False
p = 2
while p * p <= limit:
if prime[p]:
for multiple in range(p * p, limit + 1, p):
prime[multiple] = False
p += 1
return [number for number, marked in enumerate(prime) if marked]
known_primes = primes_up_to(100)
print(97 in known_primes) # True
The sieve is appropriate when the upper bound is known and many values in that interval will be queried. It is unnecessary overhead for a single, very large integer.
Testing the implementation
Use examples that cover boundaries, a small prime, a small composite, and a factor near the square-root limit:
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →def test_is_prime():
assert is_prime(-5) is False
assert is_prime(0) is False
assert is_prime(1) is False
assert is_prime(2) is True
assert is_prime(3) is True
assert is_prime(4) is False
assert is_prime(17) is True
assert is_prime(25) is False
assert is_prime(49) is False
assert is_prime(97) is True
For a command-line script, run these assertions directly with Python; for a project, place them in your test runner’s expected test file. Include perfect squares such as 49 to verify that the isqrt(n) + 1 boundary is not accidentally omitted.
Best Value
Common mistakes and fixes
- Starting at 1: Every integer is divisible by 1, so it would incorrectly classify all values as composite. Start at 2.
- Accepting 0 or 1: Add the
n < 2guard before the loop. - Stopping at
isqrt(n)without the extra one: Python excludes the range stop value. Userange(2, isqrt(n) + 1). - Using
math.sqrtfor the boundary: Floating-point conversion can lose precision for large integers. Prefer exact integerisqrt, as documented by Python. - Calling
isqrton a negative number: Reject values below 2 first. - Recomputing a sieve for every query: Build it once, retain the resulting table, and answer all bounded-range lookups from it.
Large and security-sensitive numbers
Trial division is transparent and exact, but the number of candidate divisors grows with the square root of the input. The material here does not establish a cryptographic primality algorithm, a security guarantee, or a performance threshold for cryptographic-size integers. Do not substitute this helper for a security review or a proven cryptographic-prime-testing design; select and validate an algorithm appropriate to your threat model and numeric range.
Or skip the browser setup
ScreenshotNeo is unrelated to primality testing, but it can automate clean website captures when a Python workflow also needs a page image. Its API accepts a URL in one request; cookie banners, newsletter popups and chat widgets are removed before the shot. Bot checks, blank pages and failed loads are not billed, and an MCP server lets AI agents take screenshots.
Python example (see the ScreenshotNeo documentation):
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
The equivalent requests are:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo’s free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
Frequently Asked Questions
Does the function prove that a number is prime mathematically?
Yes, for an integer input it exhausts every possible divisor from 2 through the exact square-root boundary; the factor-pair argument makes that range sufficient.
Why does the annotation say int if Python does not enforce it?
Annotations document intent for readers and type checkers. Runtime validation is still your responsibility when values come from users, files, or APIs.
Should I cache individual primality results?
Caching can help when the same values recur, but the supplied guidance does not establish a universal cache policy or performance crossover; measure your workload and memory budget.
Free tools Windows power users keep installed
One-click scans. No signup required.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

