How to resolve the algorithm The sieve of Sundaram step by step in the Go programming language
How to resolve the algorithm The sieve of Sundaram step by step in the Go programming language
Table of Contents
Problem Statement
The sieve of Eratosthenes: you've been there; done that; have the T-shirt. The sieve of Eratosthenes was ancient history when Euclid was a schoolboy. You are ready for something less than 3000 years old. You are ready for The sieve of Sundaram. Starting with the ordered set of +ve integers, mark every third starting at 4 (4;7;10...). Step through the set and if the value is not marked output 2*n+1. So from 1 to 4 output 3 5 7. 4 is marked so skip for 5 and 6 output 11 and 13. 7 is marked, so no output but now also mark every fifth starting at 12 (12;17;22...) as per to 10 and now mark every seventh starting at 17 (17;24;31....) as per for every further third element (13;16;19...) mark every (9th;11th;13th;...) element. The output will be the ordered set of odd primes. Using your function find and output the first 100 and the millionth Sundaram prime. The faithless amongst you may compare the results with those generated by The sieve of Eratosthenes. Comment on the Sundaram Sieve In case casual readers and programmers read the above blurb and get the impression that something several thousand years newer must needs be better than the "old" Sieve of Eratosthenes (SoE), do note the only difference between the Sieve of Sundaram (SoS) and the odds-only SoE is that the SoS marks as composite/"culls" according to all odd "base" numbers as is quite clear in the above description of how to implement it and the above linked Wikipedia article (updated), and the SoE marks as composite/"culls" according to only the previously determined unmarked primes (which are all odd except for two, which is not used for the "odds-only" algorithm); the time complexity (which relates to the execution time) is therefore O(n log n) for the SoS and O(n log log n) for the SoE, which difference can make a huge difference to the time it takes to sieve as the ranges get larger. It takes about a billion "culls" to sieve odds-only to a billion for the SoE, whereas it takes about 2.28 billion "culls" to cull to the same range for the SoS, which implies that the SoS must be about this ratio slower for this range with the memory usage identical. Why would one choose the SoS over the SoE to save a single line of code at the cost of this much extra time? The Wren comparison at the bottom of this page makes that clear, as would implementing the same in any language.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm The sieve of Sundaram step by step in the Go programming language
The provided Go program implements the Sieve of Sundaram and Sieve of Eratosthenes algorithms to generate prime numbers up to a specified limit. Let's break down the code step by step:
-
Imports:
- The program imports several packages:
"fmt"
for input/output"math"
for mathematical operations"rcu"
for utility functions (not shown in the code snippet you provided)"time"
to measure the execution time
- The program imports several packages:
-
Constants and Variables:
const limit = int(16e6)
: Sets a limit up to which prime numbers will be generated.
-
sos
Function (Sieve of Sundaram):- The
sos
function takes an integern
as input and returns a slice of prime numbers up ton
. - It uses the Sieve of Sundaram algorithm to generate odd prime numbers less than or equal to
n
. - It initializes a slice of booleans
marked
to track which numbers have been marked as non-prime. - It loops through numbers up to the square root of
n
and marks their multiples as non-prime. - Finally, it collects the unmarked numbers (odd primes) and returns them as a slice.
- The
-
soe
Function (Sieve of Eratosthenes):- The
soe
function is similar tosos
, but it uses the Sieve of Eratosthenes algorithm to generate all prime numbers (odd and even) up ton
. - It follows a similar approach as
sos
but initializesmarked
for all numbers (not just odd).
- The
-
main
Function:- In the
main
function, the program:- Generates primes up to the specified
limit
using both the Sieve of Sundaram and the Sieve of Eratosthenes. - Measures the execution time for each algorithm.
- Prints the results, including the first 100 odd primes generated by the Sieve of Sundaram and the millionth Sundaram prime.
- Generates primes up to the specified
- In the
-
Commatize
Function (from thercu
Package):- This function is not included in the provided code snippet but is likely used for formatting numbers with commas for readability.
In summary, this program generates prime numbers using the Sieve of Sundaram and Sieve of Eratosthenes algorithms and compares their performance. It demonstrates the efficiency of the Sieve of Sundaram in generating odd primes.
Source code in the go programming language
package main
import (
"fmt"
"math"
"rcu"
"time"
)
func sos(n int) []int {
if n < 3 {
return []int{}
}
var primes []int
k := (n-3)/2 + 1
marked := make([]bool, k) // all false by default
limit := (int(math.Sqrt(float64(n)))-3)/2 + 1
for i := 0; i < limit; i++ {
p := 2*i + 3
s := (p*p - 3) / 2
for j := s; j < k; j += p {
marked[j] = true
}
}
for i := 0; i < k; i++ {
if !marked[i] {
primes = append(primes, 2*i+3)
}
}
return primes
}
// odds only
func soe(n int) []int {
if n < 3 {
return []int{}
}
var primes []int
k := (n-3)/2 + 1
marked := make([]bool, k) // all false by default
limit := (int(math.Sqrt(float64(n)))-3)/2 + 1
for i := 0; i < limit; i++ {
if !marked[i] {
p := 2*i + 3
s := (p*p - 3) / 2
for j := s; j < k; j += p {
marked[j] = true
}
}
}
for i := 0; i < k; i++ {
if !marked[i] {
primes = append(primes, 2*i+3)
}
}
return primes
}
func main() {
const limit = int(16e6) // say
start := time.Now()
primes := sos(limit)
elapsed := int(time.Since(start).Milliseconds())
climit := rcu.Commatize(limit)
celapsed := rcu.Commatize(elapsed)
million := rcu.Commatize(1e6)
millionth := rcu.Commatize(primes[1e6-1])
fmt.Printf("Using the Sieve of Sundaram generated primes up to %s in %s ms.\n\n", climit, celapsed)
fmt.Println("First 100 odd primes generated by the Sieve of Sundaram:")
for i, p := range primes[0:100] {
fmt.Printf("%3d ", p)
if (i+1)%10 == 0 {
fmt.Println()
}
}
fmt.Printf("\nThe %s Sundaram prime is %s\n", million, millionth)
start = time.Now()
primes = soe(limit)
elapsed = int(time.Since(start).Milliseconds())
celapsed = rcu.Commatize(elapsed)
millionth = rcu.Commatize(primes[1e6-1])
fmt.Printf("\nUsing the Sieve of Eratosthenes would have generated them in %s ms.\n", celapsed)
fmt.Printf("\nAs a check, the %s Sundaram prime would again have been %s\n", million, millionth)
}
You may also check:How to resolve the algorithm Combinations with repetitions step by step in the Nim programming language
You may also check:How to resolve the algorithm Hofstadter Q sequence step by step in the Modula-2 programming language
You may also check:How to resolve the algorithm Loops/Infinite step by step in the Logo programming language
You may also check:How to resolve the algorithm Shoelace formula for polygonal area step by step in the VBScript programming language
You may also check:How to resolve the algorithm Permutations step by step in the OCaml programming language