How to resolve the algorithm Chernick's Carmichael numbers step by step in the Go programming language
How to resolve the algorithm Chernick's Carmichael numbers step by step in the Go programming language
Table of Contents
Problem Statement
In 1939, Jack Chernick proved that, for n ≥ 3 and m ≥ 1: is a Carmichael number if all the factors are primes and, for n > 4, m is a multiple of 2^(n-4).
For n = 5, the smallest number m that satisfy Chernick's conditions, is m = 380, therefore U(5, 380) is the smallest Chernick's Carmichael number with 5 prime factors. U(5, 380) is a Chernick's Carmichael number because m = 380 is a multiple of 2^(n-4), where n = 5, and the factors { (6380 + 1), (12380 + 1), (18380 + 1), (36380 + 1), (72*380 + 1) } are all prime numbers.
For n ≥ 3, let a(n) be the smallest Chernick's Carmichael number with n prime factors.
Note: it's perfectly acceptable to show the terms in factorized form:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Chernick's Carmichael numbers step by step in the Go programming language
The provided Go (*) code finds and prints the values for the Carmichael numbers, a(n), within a specified range. Carmichael numbers are special numbers that satisfy certain mathematical properties related to Carmichael functions, which are defined as:
a(n) = Π(p - 1) mod p^n
p
is a prime number that divides(n+1)
To efficiently calculate these values, the code uses optimizations and primality tests to determine Carmichael numbers within a given range, then prints the results.
Here's a detailed breakdown of the code:
package main
import (
"fmt"
big "github.com/ncw/gmp"
)
This section imports the necessary libraries, including the GMP library (github.com/ncw/gmp
), which provides high-precision arithmetic operations.
const (
min = 3
max = 10
)
var (
prod = new(big.Int)
fact = new(big.Int)
factors = [max]uint64{}
bigFactors = [max]*big.Int{}
)
Here, constants and variables are being declared:
min
andmax
define the range of Carmichael numbers to be computed.prod
andfact
arebig.Int
variables used for intermediate calculations.factors
is an array ofuint64
values to store prime factors of the Carmichael numbers.bigFactors
is an array of*big.Int
values to storebig.Int
representations of the prime factors.
func init() {
for i := 0; i < max; i++ {
bigFactors[i] = big.NewInt(0)
}
}
This initializes the bigFactors
array with big.Int
values set to zero.
func isPrimePretest(k uint64) bool {
if k%3 == 0 || k%5 == 0 || k%7 == 0 || k%11 == 0 ||
k%13 == 0 || k%17 == 0 || k%19 == 0 || k%23 == 0 {
return k <= 23
}
return true
}
The isPrimePretest
function performs a quick primality test by checking if the given number k
is divisible by a set of small prime numbers. If k
is divisible by any of these primes and is not equal to 23, it returns false
, indicating that k
is not prime. Otherwise, it returns true
, indicating that k
is likely prime.
func ccFactors(n, m uint64) bool {
if !isPrimePretest(6*m + 1) {
return false
}
if !isPrimePretest(12*m + 1) {
return false
}
factors[0] = 6*m + 1
factors[1] = 12*m + 1
t := 9 * m
for i := uint64(1); i <= n-2; i++ {
tt := (t << i) + 1
if !isPrimePretest(tt) {
return false
}
factors[i+1] = tt
}
for i := 0; i < int(n); i++ {
fact.SetUint64(factors[i])
if !fact.ProbablyPrime(0) {
return false
}
bigFactors[i].Set(fact)
}
return true
}
The ccFactors
function takes two uint64
values, n
and m
, as input and checks whether n
meets the criteria to be a Carmichael number. It does this by performing the following steps:
- It first applies the
isPrimePretest
function to quickly check if the required prime factors (6m + 1 and 12m + 1) are likely to be prime. If not, it returnsfalse
. - It populates the
factors
array with the required prime factors and their powers. - It iterates from
i = 1
ton-2
and computes the next prime factor,tt
, required for the Carmichael function computation, using bit shifts and addition. It again applies theisPrimePretest
function to ensure thattt
is likely prime. - It stores the found prime factors in the
factors
array. - It converts the prime factors in the
factors
array tobig.Int
values and stores them in thebigFactors
array. - It checks if all the converted prime factors are probably prime using the
ProbablyPrime
method. If any of them are not probably prime, it returnsfalse
. - If all checks pass, it returns
true
, indicating thatn
satisfies the Carmichael number property.
func prodFactors(n uint64) *big.Int {
prod.Set(bigFactors[0])
for i := 1; i < int(n); i++ {
prod.Mul(prod, bigFactors[i])
}
return prod
}
The prodFactors
function takes n
as input and computes the product of prime factors stored in the bigFactors
array. It returns the resulting big.Int
value.
func ccNumbers(start, end uint64) {
for n := start; n <= end; n++ {
mult := uint64(1)
if n > 4 {
mult = 1 << (n - 4)
}
if n > 5 {
mult *= 5
}
m := mult
for {
if ccFactors(n, m) {
num := prodFactors(n)
fmt.Printf("a(%d) = %d\n", n, num)
fmt.Printf("m(%d) = %d\n", n, m)
fmt.Println("Factors:", factors[:n], "\n")
break
}
m += mult
}
}
}
The ccNumbers
function is the main loop that iterates through the range of Carmichael numbers specified by start
and end
to find and print Carmichael
numbers. It does this by:
- Calculating the multiplier
mult
based on the value ofn
. - Starting with
m
equal tomult
, it repeatedly calls theccFactors
function, incrementingm
bymult
each time, until it finds a valid Carmichael number. - Once a valid Carmichael number is found, it prints the value of the Carmichael function
a(n)
, the correspondingm
value, and the prime factors used in the calculation.
In summary, this code efficiently computes and prints Carmichael numbers within a specified range by employing optimizations and primality tests to reduce the computational complexity and improve accuracy.
Source code in the go programming language
package main
import (
"fmt"
"math/big"
)
var (
zero = new(big.Int)
prod = new(big.Int)
fact = new(big.Int)
)
func ccFactors(n, m uint64) (*big.Int, bool) {
prod.SetUint64(6*m + 1)
if !prod.ProbablyPrime(0) {
return zero, false
}
fact.SetUint64(12*m + 1)
if !fact.ProbablyPrime(0) { // 100% accurate up to 2 ^ 64
return zero, false
}
prod.Mul(prod, fact)
for i := uint64(1); i <= n-2; i++ {
fact.SetUint64((1<<i)*9*m + 1)
if !fact.ProbablyPrime(0) {
return zero, false
}
prod.Mul(prod, fact)
}
return prod, true
}
func ccNumbers(start, end uint64) {
for n := start; n <= end; n++ {
m := uint64(1)
if n > 4 {
m = 1 << (n - 4)
}
for {
num, ok := ccFactors(n, m)
if ok {
fmt.Printf("a(%d) = %d\n", n, num)
break
}
if n <= 4 {
m++
} else {
m += 1 << (n - 4)
}
}
}
}
func main() {
ccNumbers(3, 9)
}
package main
import (
"fmt"
big "github.com/ncw/gmp"
)
const (
min = 3
max = 10
)
var (
prod = new(big.Int)
fact = new(big.Int)
factors = [max]uint64{}
bigFactors = [max]*big.Int{}
)
func init() {
for i := 0; i < max; i++ {
bigFactors[i] = big.NewInt(0)
}
}
func isPrimePretest(k uint64) bool {
if k%3 == 0 || k%5 == 0 || k%7 == 0 || k%11 == 0 ||
k%13 == 0 || k%17 == 0 || k%19 == 0 || k%23 == 0 {
return k <= 23
}
return true
}
func ccFactors(n, m uint64) bool {
if !isPrimePretest(6*m + 1) {
return false
}
if !isPrimePretest(12*m + 1) {
return false
}
factors[0] = 6*m + 1
factors[1] = 12*m + 1
t := 9 * m
for i := uint64(1); i <= n-2; i++ {
tt := (t << i) + 1
if !isPrimePretest(tt) {
return false
}
factors[i+1] = tt
}
for i := 0; i < int(n); i++ {
fact.SetUint64(factors[i])
if !fact.ProbablyPrime(0) {
return false
}
bigFactors[i].Set(fact)
}
return true
}
func prodFactors(n uint64) *big.Int {
prod.Set(bigFactors[0])
for i := 1; i < int(n); i++ {
prod.Mul(prod, bigFactors[i])
}
return prod
}
func ccNumbers(start, end uint64) {
for n := start; n <= end; n++ {
mult := uint64(1)
if n > 4 {
mult = 1 << (n - 4)
}
if n > 5 {
mult *= 5
}
m := mult
for {
if ccFactors(n, m) {
num := prodFactors(n)
fmt.Printf("a(%d) = %d\n", n, num)
fmt.Printf("m(%d) = %d\n", n, m)
fmt.Println("Factors:", factors[:n], "\n")
break
}
m += mult
}
}
}
func main() {
ccNumbers(min, max)
}
You may also check:How to resolve the algorithm Conditional structures step by step in the МК-61/52 programming language
You may also check:How to resolve the algorithm Prime decomposition step by step in the Seed7 programming language
You may also check:How to resolve the algorithm Repeat step by step in the Rust programming language
You may also check:How to resolve the algorithm Anonymous recursion step by step in the Racket programming language
You may also check:How to resolve the algorithm Greedy algorithm for Egyptian fractions step by step in the RPL programming language