25
loading...
This website collects cookies to deliver better user experience
TL;DR: Only check numbers up to the square root of the upper limit.
After that, every number up to that limit will be accurately marked, because math is cool.
The factors can both be identical to sqrt(n).
49 for example
TL;DR: Start unmarking multiples of a number at that number squared.
All multiples below are already unmarked, because math is cool.
upper_bound
.I named that variable optimus_prime
while writing code for this post, because I thought that was funny
upper_bound
and call it sieve
.True
for prime, False
for not)def primes_up_to(upper_bound):
# initialise sieve that marks all numbers as prime
sieve = [True] * (upper_bound + 1)
upper_bound
.def primes_up_to(upper_bound):
# initialise sieve that marks all numbers as prime
sieve = [True] * (upper_bound + 1)
# 0 and 1 are not prime
sieve[0] = False
sieve[1] = False
upper_bound
.sieve
with that number.import math
def primes_up_to(upper_bound):
# initialise sieve that marks all numbers as prime
sieve = [True] * (upper_bound + 1)
# 0 and 1 are not prime
sieve[0] = False
sieve[1] = False
# iterate up to square root of upper_bound
# reason: if one factor of num is bigger than sqrt(upper_bound),
# an other factor _must_ be smaller than sqrt(upper_bound)
for num in range(2, math.floor(math.sqrt(upper_bound)) + 1):
# if sieve[num] is true, then num is prime
if sieve[num]:
True
, the number is prime and we unmark every multiple before moving on to the next step of our loop.upper_bound
.sieve
at that number's index to False
.import math
def primes_up_to(upper_bound):
# initialise sieve that marks all numbers as prime
sieve = [True] * (upper_bound + 1)
# 0 and 1 are not prime
sieve[0] = False
sieve[1] = False
# iterate up to square root of upper_bound
# reason: if one factor of num is bigger than sqrt(upper_bound),
# an other factor _must_ be smaller than sqrt(upper_bound)
for num in range(2, math.floor(math.sqrt(upper_bound)) + 1):
# if sieve[num] is true, then num is prime
if sieve[num]:
# unmark all multiples
# start unmarking at num squared
# every smaller multiple has already been unmarked in previous iterations
for multiple in range(num ** 2, upper_bound + 1, num):
sieve[multiple] = False
sieve
will be full of booleans corresponding to the primeness of every possible index to that list.true
into a new list, and presto, primes.import math
def primes_up_to(upper_bound):
# initialise sieve that marks all numbers as prime
sieve = [True] * (upper_bound + 1)
# 0 and 1 are not prime
sieve[0] = False
sieve[1] = False
# iterate up to square root of upper_bound
# reason: if one factor of num is bigger than sqrt(upper_bound),
# an other factor _must_ be smaller than sqrt(upper_bound)
for num in range(2, math.floor(math.sqrt(upper_bound)) + 1):
# if sieve[num] is true, then num is prime
if sieve[num]:
# unmark all multiples
# start unmarking at num squared
# every smaller multiple has already been unmarked in previous iterations
for multiple in range(num ** 2, upper_bound + 1, num):
sieve[multiple] = False
# sieve is done, turn `True` into numbers
return [idx for idx, mark in enumerate(sieve) if mark]
upper_bound
.primes_up_to(16)
returns [2, 3, 5, 7, 11, 13]
.primes_up_to(17)
returns [2, 3, 5, 7, 11, 13, 17]
.primes_up_to(18)
returns [2, 3, 5, 7, 11, 13, 17]
.primes_up_to(19)
returns [2, 3, 5, 7, 11, 13, 17, 19]
.pub fn primes_up_to(upper_bound: usize) -> Vec<usize> {
// initialise sieve that marks all numbers as prime
let mut sieve = vec![true; upper_bound + 1];
// 0 and 1 are not prime
sieve[0] = false;
sieve[1] = false;
// iterate up to square root of upper_bound
// reason: if one factor of num is bigger than sqrt(upper_bound),
// an other factor _must_ be smaller than sqrt(upper_bound)
for num in 2..=(upper_bound as f64).sqrt() as usize + 1 {
// if sieve[num] is true, then num is prime
if sieve[num] {
// unmark all multiples
// start unmarking at num squared
// every smaller multiple has already been unmarked in previous iterations
for multiple in (num * num..=upper_bound).step_by(num) {
sieve[multiple] = false;
}
}
}
// sieve is done, turn `true` into numbers
sieve
.iter()
.enumerate()
.filter_map(|(idx, mark)| match mark {
true => Some(idx),
false => None,
})
.collect()
}
function primesUpTo(upperBound) {
// initialise sieve that marks all numbers as prime
const sieve = Array.from({ length: upperBound + 1 }, () => true);
// 0 and 1 are not prime
sieve[0] = false;
sieve[1] = false;
// iterate up to square root of upperBound
// reason: if one factor of num is bigger than sqrt(upperBound),
// an other factor _must_ be smaller than sqrt(upperBound)
for (let num = 2; num <= Math.sqrt(upperBound) + 1; num++) {
// if sieve[num] is true, then num is prime
if (sieve[num]) {
// unmark all multiples
// start unmarking at num squared
// every smaller multiple has already been unmarked in previous iterations
for (let multiple = num ** 2; multiple <= upperBound; multiple += num) {
sieve[multiple] = false;
}
}
}
// sieve is done, turn `true` into numbers
const primes = [];
for (const [idx, mark] of sieve.entries()) {
mark && primes.push(idx);
}
return primes;
}
import math
def primes_up_to(upper_bound):
# initialise sieve that marks all numbers as prime
sieve = [True] * (upper_bound + 1)
# 0 and 1 are not prime
sieve[0] = False
sieve[1] = False
# iterate up to square root of upper_bound
# reason: if one factor of num is bigger than sqrt(upper_bound),
# an other factor _must_ be smaller than sqrt(upper_bound)
for num in range(2,math.floor(math.sqrt(upper_bound)) + 1):
# if sieve[num] is true, then num is prime
if sieve[num]:
# unmark all multiples
# start unmarking at num squared
# every smaller multiple has already been unmarked in previous iterations
for multiple in range(num**2, upper_bound + 1, num):
sieve[multiple] = False
# sieve is done, turn `True` into numbers
return [idx for idx, mark in enumerate(sieve) if mark]