How to resolve the algorithm Minkowski question-mark function step by step in the Go programming language
How to resolve the algorithm Minkowski question-mark function step by step in the Go programming language
Table of Contents
Problem Statement
The Minkowski question-mark function converts the continued fraction representation [a0; a1, a2, a3, ...] of a number into a binary decimal representation in which the integer part a0 is unchanged and the a1, a2, ... become alternating runs of binary zeroes and ones of those lengths. The decimal point takes the place of the first zero. Thus, ?(31/7) = 71/16 because 31/7 has the continued fraction representation [4;2,3] giving the binary expansion 4 + 0.01112. Among its interesting properties is that it maps roots of quadratic equations, which have repeating continued fractions, to rational numbers, which have repeating binary digits. The question-mark function is continuous and monotonically increasing, so it has an inverse.
Don't worry about precision error in the last few digits.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Minkowski question-mark function step by step in the Go programming language
Minkowski's Question Mark Function
The provided Go code is an implementation of Minkowski's question mark function and its inverse.
Minkowski's Question Mark Function
The function minkowski(x)
computes the continued fraction expansion of x and then uses it to calculate the Minkowski question mark function.
The Minkowski question mark function is defined as follows:
?(x) = floor(x) + ?(x - floor(x)) if x > 1 or x < 0
?(1) = 1
?(0) = 0
?(x) = y + d where:
y is the continued fraction expansion of x
d = 1/2^n, where n is the number of times y can be added to itself without changing
**Minkowski's Inverse Question Mark Function**
The function `minkowskiInv(x)` computes the inverse of Minkowski's question mark function using a continued fraction expansion.
The inverse Minkowski question mark function is defined as follows:
?^-1(x) = floor(x) + ?^-1(x - floor(x)) if x > 1 or x < 0 ?^-1(1) = 1 ?^-1(0) = 0 ?^-1(x) = 1 / (c[n] + 1 / (c[n-1] + ... + 1 / (c[0] + 1 / d))), where: d = 1/2^n, where n is the number of times y can be added to itself without changing c[i] is the ith element of the continued fraction expansion of x Output:
The program prints three pairs of values:
minkowski(0.5*(1+math.Sqrt(5)))
and5.0/3.0
, which are equal within the specified precision.minkowskiInv(-5.0/9.0)
and(math.Sqrt(13)-7)/6
, which are equal within the specified precision.minkowski(minkowskiInv(0.718281828))
andminkowskiInv(minkowski(0.1213141516171819))
, which are equal within the specified precision.
These results demonstrate that the implementation correctly computes the Minkowski question mark function and its inverse.
Source code in the go programming language
package main
import (
"fmt"
"math"
)
const MAXITER = 151
func minkowski(x float64) float64 {
if x > 1 || x < 0 {
return math.Floor(x) + minkowski(x-math.Floor(x))
}
p := uint64(x)
q := uint64(1)
r := p + 1
s := uint64(1)
d := 1.0
y := float64(p)
for {
d = d / 2
if y+d == y {
break
}
m := p + r
if m < 0 || p < 0 {
break
}
n := q + s
if n < 0 {
break
}
if x < float64(m)/float64(n) {
r = m
s = n
} else {
y = y + d
p = m
q = n
}
}
return y + d
}
func minkowskiInv(x float64) float64 {
if x > 1 || x < 0 {
return math.Floor(x) + minkowskiInv(x-math.Floor(x))
}
if x == 1 || x == 0 {
return x
}
contFrac := []uint32{0}
curr := uint32(0)
count := uint32(1)
i := 0
for {
x *= 2
if curr == 0 {
if x < 1 {
count++
} else {
i++
t := contFrac
contFrac = make([]uint32, i+1)
copy(contFrac, t)
contFrac[i-1] = count
count = 1
curr = 1
x--
}
} else {
if x > 1 {
count++
x--
} else {
i++
t := contFrac
contFrac = make([]uint32, i+1)
copy(contFrac, t)
contFrac[i-1] = count
count = 1
curr = 0
}
}
if x == math.Floor(x) {
contFrac[i] = count
break
}
if i == MAXITER {
break
}
}
ret := 1.0 / float64(contFrac[i])
for j := i - 1; j >= 0; j-- {
ret = float64(contFrac[j]) + 1.0/ret
}
return 1.0 / ret
}
func main() {
fmt.Printf("%19.16f %19.16f\n", minkowski(0.5*(1+math.Sqrt(5))), 5.0/3.0)
fmt.Printf("%19.16f %19.16f\n", minkowskiInv(-5.0/9.0), (math.Sqrt(13)-7)/6)
fmt.Printf("%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)),
minkowskiInv(minkowski(0.1213141516171819)))
}
You may also check:How to resolve the algorithm Knuth shuffle step by step in the Elixir programming language
You may also check:How to resolve the algorithm Mutex step by step in the Racket programming language
You may also check:How to resolve the algorithm Reverse a string step by step in the PL/I programming language
You may also check:How to resolve the algorithm Weird numbers step by step in the Phix programming language
You may also check:How to resolve the algorithm Literals/Integer step by step in the REBOL programming language