Minkowski question-mark function: Difference between revisions

Add C# implementation
(→‎{{header|Haskell}}: added solution)
(Add C# implementation)
 
(23 intermediate revisions by 8 users not shown)
Line 30:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">-V MAXITER = 151
 
F minkowski(x) -> Float
Line 119:
print(‘#2.16 #2.16’.format(minkowski(0.5 * (1 + sqrt(5))), 5.0 / 3.0))
print(‘#2.16 #2.16’.format(minkowski_inv(-5.0 / 9.0), (sqrt(13) - 7) / 6))
print(‘#2.16 #2.16’.format(minkowski(minkowski_inv(0.718281828)), minkowski_inv(minkowski(0.1213141516171819))))</langsyntaxhighlight>
 
{{out}}
Line 128:
</pre>
 
=={{header|C#}}==
{{trans|Go}}
<syntaxhighlight lang="C#">
using System;
 
class Program
{
const int MAXITER = 151;
 
static double Minkowski(double x)
{
if (x > 1 || x < 0)
{
return Math.Floor(x) + Minkowski(x - Math.Floor(x));
}
ulong p = (ulong)x;
ulong q = 1;
ulong r = p + 1;
ulong s = 1;
double d = 1.0;
double y = (double)p;
while (true)
{
d = d / 2;
if (y + d == y)
{
break;
}
ulong m = p + r;
if (m < 0 || p < 0)
{
break;
}
ulong n = q + s;
if (n < 0)
{
break;
}
if (x < (double)m / (double)n)
{
r = m;
s = n;
}
else
{
y = y + d;
p = m;
q = n;
}
}
return y + d;
}
 
static double MinkowskiInv(double x)
{
if (x > 1 || x < 0)
{
return Math.Floor(x) + MinkowskiInv(x - Math.Floor(x));
}
if (x == 1 || x == 0)
{
return x;
}
uint[] contFrac = new uint[] { 0 };
uint curr = 0;
uint count = 1;
int i = 0;
while (true)
{
x *= 2;
if (curr == 0)
{
if (x < 1)
{
count++;
}
else
{
i++;
Array.Resize(ref contFrac, i + 1);
contFrac[i - 1] = count;
count = 1;
curr = 1;
x--;
}
}
else
{
if (x > 1)
{
count++;
x--;
}
else
{
i++;
Array.Resize(ref contFrac, i + 1);
contFrac[i - 1] = count;
count = 1;
curr = 0;
}
}
if (x == Math.Floor(x))
{
contFrac[i] = count;
break;
}
if (i == MAXITER)
{
break;
}
}
double ret = 1.0 / contFrac[i];
for (int j = i - 1; j >= 0; j--)
{
ret = contFrac[j] + 1.0 / ret;
}
return 1.0 / ret;
}
 
static void Main(string[] args)
{
Console.WriteLine("{0,19:0.0000000000000000} {1,19:0.0000000000000000}", Minkowski(0.5 * (1 + Math.Sqrt(5))), 5.0 / 3.0);
Console.WriteLine("{0,19:0.0000000000000000} {1,19:0.0000000000000000}", MinkowskiInv(-5.0 / 9.0), (Math.Sqrt(13) - 7) / 6);
Console.WriteLine("{0,19:0.0000000000000000} {1,19:0.0000000000000000}", Minkowski(MinkowskiInv(0.718281828)),
MinkowskiInv(Minkowski(0.1213141516171819)));
}
}
</syntaxhighlight>
{{out}}
<pre>
1.6666666666697000 1.6666666666666700
-0.5657414540893350 -0.5657414540893350
0.7182818280000090 0.1213141516171820
 
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="c++">
#include <cmath>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <vector>
 
constexpr int32_t MAX_ITERATIONS = 151;
 
double minkowski(const double& x) {
if ( x < 0 || x > 1 ) {
return floor(x) + minkowski(x - floor(x));
}
 
int64_t p = (int64_t) x;
int64_t q = 1;
int64_t r = p + 1;
int64_t s = 1;
double d = 1.0;
double y = (double) p;
 
while ( true ) {
d /= 2;
if ( d == 0.0 ) {
break;
}
 
int64_t m = p + r;
if ( m < 0 || p < 0 ) {
break;
}
 
int64_t n = q + s;
if ( n < 0 ) {
break;
}
 
if ( x < (double) m / n ) {
r = m;
s = n;
} else {
y += d;
p = m;
q = n;
}
}
return y + d;
}
 
double minkowski_inverse(double x) {
if ( x < 0 || x > 1 ) {
return floor(x) + minkowski_inverse(x - floor(x));
}
 
if ( x == 0 || x == 1 ) {
return x;
}
 
std::vector<int32_t> continued_fraction(1, 0);
int32_t current = 0;
int32_t count = 1;
int32_t i = 0;
 
while ( true ) {
x *= 2;
if ( current == 0 ) {
if ( x < 1 ) {
count += 1;
} else {
continued_fraction.emplace_back(0);
continued_fraction[i] = count;
 
i += 1;
count = 1;
current = 1;
x -= 1;
}
} else {
if ( x > 1 ) {
count += 1;
x -= 1;
} else {
continued_fraction.emplace_back(0);
continued_fraction[i] = count;
 
i += 1;
count = 1;
current = 0;
}
}
 
if ( x == floor(x) ) {
continued_fraction[i] = count;
break;
}
 
if ( i == MAX_ITERATIONS ) {
break;
}
}
 
double reciprocal = 1.0 / continued_fraction[i];
for ( int32_t j = i - 1; j >= 0; --j ) {
reciprocal = continued_fraction[j] + 1.0 / reciprocal;
}
 
return 1.0 / reciprocal;
}
 
int main() {
std::cout << std::setw(20) << std::fixed << std::setprecision(16) << minkowski(0.5 * ( 1 + sqrt(5) ))
<< std::setw(20) << 5.0 / 3.0 << std::endl;
std::cout << std::setw(20) << minkowski_inverse(-5.0 / 9.0)
<< std::setw(20) << ( sqrt(13) - 7 ) / 6 << std::endl;
std::cout << std::setw(20) << minkowski(minkowski_inverse(0.718281828182818))
<< std::setw(20) << 0.718281828182818 << std::endl;
std::cout << std::setw(20) << minkowski_inverse(minkowski(0.1213141516271819))
<< std::setw(20) << 0.1213141516171819 << std::endl;
}
</syntaxhighlight>
{{ out }}
<pre>
1.6666666666696983 1.6666666666666667
-0.5657414540893351 -0.5657414540893352
0.7182818281828269 0.7182818281828180
0.1213141516171819 0.1213141516171819
</pre>
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
// Minkowski question-mark function. Nigel Galloway: July 14th., 2023
let fN g=let n=(int>>float)g in ((if g<0.0 then -1.0 else 1.0),abs n,abs (g-n))
let fI(n,_,(nl,nh))(g,_,(gl,gh))=let l,h=nl+gl,nh+gh in ((n+g)/2.0,(float l)/(float h),(l,h))
let fG n g=(max n g)-(min n g)
let fE(s,z,l)=Seq.unfold(fun(i,e)->let (n,g,_) as r=fI i e in Some((s*(z+n),s*(g+z)),if l<n then (i,r) else if l=n then (r,r) else (r,e)))((0.0,0.0,(0,1)),(1.0,1.0,(1,1)))
let fL(s,z,l)=Seq.unfold(fun(i,e)->let (n,g,_) as r=fI i e in Some((s*(z+n),s*(g+z)),if l<g then (i,r) else if l=g then (r,r) else (r,e)))((0.0,0.0,(0,1)),(1.0,1.0,(1,1)))
let f2M g=let _,(n,_)=fL(fN g)|>Seq.pairwise|>Seq.find(fun((n,_),(g,_))->(fG n g)<2.328306437e-11) in n
let m2F g=let _,(_,n)=fE(fN g)|>Seq.pairwise|>Seq.find(fun((_,n),(_,g))->(fG n g)<2.328306437e-11) in n
 
printfn $"?(φ) = 5/3 is %A{fG(f2M 1.61803398874989490253)(5.0/3.0)<2.328306437e-10}"
printfn $"?⁻¹(-5/9) = (√13-7)/6 is %A{fG(m2F(-5.0/9.0))((sqrt(13.0)-7.0)/6.0)<2.328306437e-10}"
let n=42.0/23.0 in printfn $"?⁻¹(?(n)) = n is %A{(fG(m2F(f2M n)) n)<2.328306437e-10}"
let n= -3.0/13.0 in printfn $"?(?⁻¹(n)) = n is %A{(fG(f2M(m2F n)) n)<2.328306437e-10}"
</syntaxhighlight>
{{out}}
<pre>
?(φ) = 5/3 is true
?⁻¹(-5/9) = (√13-7)/6 is true
?⁻¹(?(n)) = n is true
?(?⁻¹(n)) = n is true
</pre>
=={{header|Factor}}==
{{works with|Factor|0.99 2020-08-14}}
<langsyntaxhighlight lang="factor">USING: formatting kernel make math math.constants
math.continued-fractions math.functions math.parser
math.statistics sequences sequences.extras splitting.monotonic
Line 165 ⟶ 454:
phi ? 5 3 /f compare
-5/9 ?⁻¹ 13 sqrt 7 - 6 /f compare
0.718281828 ?⁻¹ ? 0.1213141516171819 ? ?⁻¹ compare</langsyntaxhighlight>
{{out}}
<pre>
Line 175 ⟶ 464:
=={{header|FreeBASIC}}==
 
<langsyntaxhighlight lang="freebasic">#define MAXITER 151
 
function minkowski( x as double ) as double
Line 246 ⟶ 535:
print minkowski_inv( -5./9 ), (sqr(13)-7)/6
print minkowski(minkowski_inv(0.718281828)), minkowski_inv(minkowski(0.1213141516171819))
</syntaxhighlight>
</lang>
{{out}}
<pre> 1.666666666669698 1.666666666666667
Line 254 ⟶ 543:
=={{header|Go}}==
{{trans|FreeBASIC}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 358 ⟶ 647:
fmt.Printf("%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)),
minkowskiInv(minkowski(0.1213141516171819)))
}</langsyntaxhighlight>
 
{{out}}
Line 368 ⟶ 657:
 
=={{header|Haskell}}==
 
=== Exact rational function using Farey tree ===
 
In a lazy functional language Minkowski question mark function can be implemented using one of it's basic properties:
 
Line 377 ⟶ 663:
where p/q and r/s are fractions, such that |ps - rq| = 1.
 
This recursive definition can be implemented as lazy corecursion, i.e. by generating two infinite binary trees: '''mediant'''-based FareyStern-Brocot tree, containing all rationals, and '''mean'''-based tree with corresponding values of Minkowsky ?-function. There is one-to-one correspondence between these two trees so both {{math|?(x)}} and {{math|?<sup>-1</sup>(x)}} may be implemented as mapping between them. For details see the paper [[https://habr.com/ru/post/591949/]] (in Russian).
 
<syntaxhighlight lang="haskell">import Data.Tree
First we define tools to handle trees.
 
<lang haskell>import Data.List (unfoldr)
import Data.Ratio
import Data.Tree (Tree (..), levels, unfoldTree)List
 
import Control.Monad.Zip (mzip)
intervalTree :: (a -> a -> a) -> (a, a) -> Tree a
intervalTree node = unfoldTree $
\(a, b) -> let m = node a b in (m, [(a,m), (m,b)])
 
Node a _ ==> Node b [] = const b
Node a [] ==> Node b _ = const b
Node a [l1, r1] ==> Node b [l2, r2] =
\x -> case x `compare` a of
LT -> (l1 ==> l2) x
EQ -> b
GT -> (r1 ==> r2) x
 
mkTreemirror :: (a ->Num a -=> a) -> a ->Tree a -> Tree a
mirror t = Node 0 [reflect (negate <$> t), t]
mkTree f a b = unfoldTree go (a, b)
where
goreflect (Node a [l,br]) = let m = fNode a b[reflect in (mr, [(a,m),reflect (m,b)l])
 
------------------------------------------------------------
pathBy :: Ord b => (a -> b) -> Tree a -> b -> [Either a a]
pathBy f (Node a [l,r]) x =
case x `compare` f a of
LT -> Left a : pathBy f l x
EQ -> [Right a]
GT -> Right a : pathBy f r x</lang>
 
sternBrocot :: Tree Rational
Now it is possible to define two trees:
sternBrocot = toRatio <$> intervalTree mediant ((0,1), (1,0))
where
mediant (p, q) (r, s) = (p + r, q + s)
 
<lang haskell>farey = toRatio <$> mkTree mediant (0p, 1q) (1,= 1)p % q
minkowski = toRatio <$> mkTree mean (0, 1) (1, 1)
 
minkowski :: Tree Rational
mediant (a,b) (c,d) = (a + c, b + d)
minkowski = toRatio <$> intervalTree mean ((0,1), (1,0))
mean (a,b) (c,d) = (a*d + c*b, 2*b*d)
 
toRatio (a, b) = a % b</lang>
mean (p, q) (1, 0) = (p+1, q)
mean (p, q) (r, s) = (p*s + q*r, 2*q*s)
 
 
questionMark, invQuestionMark :: Rational -> Rational
questionMark = mirror sternBrocot ==> mirror minkowski
invQuestionMark = mirror minkowski ==> mirror sternBrocot
 
------------------------------------------------------------
-- Floating point trees and functions
 
sternBrocotF :: Tree Double
sternBrocotF = mirror $ fromRational <$> sternBrocot
 
minkowskiF :: Tree Double
minkowskiF = mirror $ intervalTree mean (0, 1/0)
where
mean a b | isInfinite b = a + 1
| otherwise = (a + b) / 2
 
questionMarkF, invQuestionMarkF :: Double -> Double
questionMarkF = sternBrocotF ==> minkowskiF
invQuestionMarkF = minkowskiF ==> sternBrocotF</syntaxhighlight>
 
<pre>λ> mapM_ print $ take 4 $ levels farey
Line 419 ⟶ 734:
[1 % 16,3 % 16,5 % 16,7 % 16,9 % 16,11 % 16,13 % 16,15 % 16]</pre>
 
λ> questionMark (1/2)
Here is symmetric definitions of {{math|?(x)}} and {{math|?<sup>-1</sup>(x)}} for rational numbers:
1 % 2
λ> questionMark (2/7)
3 % 16
λ> questionMark (-22/7)
(-193) % 64
λ> invQuestionMark (3/16)
2 % 7
λ> invQuestionMark (13/256)
5 % 27</pre>
 
<pre>λ> questionMark $ (sqrt 5 + 1) / 2
<lang haskell>minkowskiQR :: Ratio Integer -> Ratio Integer
1.6666666666678793
minkowskiQR = fromFraction . fmap transform . properFraction
λ> 5/3
where
1.6666666666666667
transform = oddFunc $ lookupTree (mzip farey minkowski)
λ> invQuestionMark (-5/9)
-0.5657414540893351
λ> (sqrt 13 - 7)/6
-0.5657414540893352</pre>
 
=={{header|J}}==
invMinkowskiQR :: Ratio Integer -> Ratio Integer
invMinkowskiQR = fromFraction . fmap transform . properFraction
where
transform = oddFunc $ lookupTree (mzip minkowski farey)
 
Implementation:
fromFraction (i, f) = fromIntegral i + f
 
<syntaxhighlight lang="j">ITERCOUNT=: 52
lookupTree :: Ord a => Tree (a, c) -> a -> c
lookupTree t =
snd . either id id . last . pathBy fst t
 
minkowski=: {{
oddFunc f 0 = 0
f=. 1|y
oddFunc f x = signum x * f (abs x)</lang>
node=. *i.2 2 NB. node of Stern-Brocot tree
B=. ''
for. i.ITERCOUNT do.
B=. B, b=. f>:%/t=. +/node
node=. t (1-b)} node
end.
(<.y)+B+/ .*2^-1+i.ITERCOUNT
}}
invmink=: {{
f=. 1|y
cf=. i.0
cur=. 0 NB. 1 if generating "top" side of cf
cnt=. 1 NB. proposed continued fraction element
for. i.ITERCOUNT do.
if. f=<. f do.
cf=. cf,%cnt break.
end.
f=. f*2
b=. 1 >`<@.cur f
cf=. cf,(-.b)#cnt
cnt=. 1+b*cnt
cur=. cur=b
f=. f-cur
end.
(+%)/(<.y),cf
}}</syntaxhighlight>
 
That said, note that this algorithm introduces significant numeric instability for √7 divided by 3:
<pre>λ> minkowskiQR (1/2)
1 % 2
λ> minkowskiQR (2/7)
3 % 16
λ> minkowskiQR (-22/7)
(-193) % 64
λ> invMinkowskiQR (3/16)
2 % 7
λ> invMinkowskiQR (13/256)
5 % 27</pre>
 
<syntaxhighlight lang="j"> (minkowski@invmink - invmink@minkowski) (p:%%:)3
=== Floating point function using Farey tree ===
1.10713e_6</syntaxhighlight>
 
I see this same instability using the python implementation and appending:
Paths leading to numbers in Farey tree, give diadic representation of corresponding value of Minkowski ?-function and vice versa. So it is possible to use Farey tree to define Minkowski function and it's inverse for floating point numbers.
 
<syntaxhighlight lang="python"> print(
<lang haskell>minkowskiQF :: Double -> Double
"{:19.16f} {:19.16f}".format(
minkowskiQF = oddFunc $ fromDiadic . fmap transform . properFraction
minkowski(minkowski_inv(4.04145188432738056)),
where
minkowski_inv(minkowski(4.04145188432738056)),
transform 0 = []
)
transform f = track (fromRational <$> farey) f
)</syntaxhighlight>
 
Using an exact fraction for 4.04145188432738056 and bumping the iteration count from 52 up to 200 changes that difference to 1.43622e_12.
invMinkowskiQF :: Double -> Double
invMinkowskiQF = oddFunc $ fromFraction . fmap transform . toDiadic
where
transform [] = 0
transform f = follow (fromRational <$> farey) f
 
=={{header|Java}}==
fromDiadic :: (Int, [Int]) -> Double
<syntaxhighlight lang="java">
fromDiadic = fromFraction . fmap (foldr go 0 . take 55)
import java.util.ArrayList;
where
import java.util.List;
go x r = (r + fromIntegral x)/2
 
public final class MinkowskiQuestionMarkFunction {
toDiadic :: Double -> (Int, [Int])
toDiadic = fmap (unfoldr go) . properFraction
where
go x = case properFraction (x * 2) of
(0, 0) -> Nothing
(i, f) -> Just (i `mod` 2, f)
 
public static void main(String[] aArgs) {
track :: Ord a => Tree a -> a -> [Int]
System.out.println(String.format("%20.16f%20.16f", minkowski(0.5 * ( 1 + Math.sqrt(5) )), 5.0 / 3.0));
track t = fmap (either (const 0) (const 1)) . pathBy id t
System.out.println(String.format("%20.16f%20.16f", minkowskiInverse(-5.0 / 9.0), ( Math.sqrt(13) - 7 ) / 6 ));
System.out.println(String.format("%20.16f%20.16f", minkowski(minkowskiInverse(0.718281828)), 0.718281828));
System.out.println(String.format("%20.16f%20.16f",
minkowskiInverse(minkowski(0.1213141516271819)), 0.1213141516171819));
}
private static double minkowski(double aX) {
if ( aX < 0 || aX > 1 ) {
return Math.floor(aX) + minkowski(aX - Math.floor(aX));
}
long p = (long) aX;
long q = 1;
long r = p + 1;
long s = 1;
double d = 1.0;
double y = (double) p;
while ( true ) {
d /= 2;
if ( d == 0.0 ) {
break;
}
long m = p + r;
if ( m < 0 || p < 0 ) {
break;
}
long n = q + s;
if ( n < 0 ) {
break;
}
if ( aX < (double) m / n ) {
r = m;
s = n;
} else {
y += d;
p = m;
q = n;
}
}
return y + d;
}
private static double minkowskiInverse(double aX) {
if ( aX < 0 || aX > 1 ) {
return Math.floor(aX) + minkowskiInverse(aX - Math.floor(aX));
}
if ( aX == 0 || aX == 1 ) {
return aX;
}
List<Integer> continuedFraction = new ArrayList<Integer>();
continuedFraction.add(0);
int current = 0;
int count = 1;
int i = 0;
while ( true ) {
aX *= 2;
if ( current == 0 ) {
if ( aX < 1 ) {
count += 1;
} else {
continuedFraction.add(0);
continuedFraction.set(i, count);
 
i += 1;
follow :: Tree a -> [Int] -> a
count = 1;
follow t lst = rootLabel $ foldl (\t -> (subForest t !!)) t $ init lst</lang>
current = 1;
aX -= 1;
}
} else {
if ( aX > 1 ) {
count += 1;
aX -= 1;
} else {
continuedFraction.add(0);
continuedFraction.set(i, count);
 
i += 1;
<pre>λ> minkowskiQF (1/2)
count = 1;
0.5
current = 0;
λ> minkowskiQF (2/7)
}
0.1875
}
λ> minkowskiQF (-22/7)
-3.015625
λ> invMinkowskiQF (3/16)
0.2857142857142857
λ> invMinkowskiQF (13/256)
0.18518518518518517
λ> minkowskiQF (sqrt 2)
1.4000000000003183</pre>
 
if ( aX == Math.floor(aX) ) {
The task and tests:
continuedFraction.set(i, count);
break;
}
 
if ( i == MAX_ITERATIONS ) {
<lang haskell>-- sequence of all positive rationals
break;
sternBrocot = toRatio <$> mkTree mediant (0, 1) (1, 0)
}
rationals = concat (levels sternBrocot)
}
 
double reciprocal = 1.0 / continuedFraction.get(i);
testEq f g = all (\x -> f x == g x)
testEqF f g = allfor (\x ->int absj (f= xi - g1; x)j <>= 1e0; j-11- ) {
reciprocal = continuedFraction.get(j) + 1.0 / reciprocal;
}
 
return 1.0 / reciprocal;
testIds :: [[Ratio Integer] -> Bool]
}
testIds =
[ testEq (invMinkowskiQR . minkowskiQR) id
private static final int MAX_ITERATIONS = 150;
, testEq (minkowskiQR . invMinkowskiQR) id . fmap minkowskiQR
, testEqF (invMinkowskiQF . minkowskiQF) id . fmap fromRational
, testEqF (minkowskiQF . invMinkowskiQF) id . fmap fromRational
, testEq (minkowskiQF . fromRational) (fromRational . minkowskiQR) ]</lang>
 
}
λ> minkowskiQF $ (sqrt 5 + 1) / 2
</syntaxhighlight>
1.6666666666678793
{{ out }}
λ> 5/3
<pre>
1.6666666666666667
1.6666666666696983 1.6666666666666667
λ> invMinkowskiQF (-5/9)
-0.5657414540893351 -0.5657414540893352
0.7182818280000092 0.7182818280000000
λ> (sqrt 13 - 7)/6
0.1213141516271825 0.1213141516171819
-0.5657414540893352
</pre>
λ> sequence testIds $ take 1000 rationals
[True,True,True,True,True]</pre>
 
=={{header|Julia}}==
 
{{trans|FreeBASIC}}
<langsyntaxhighlight lang="julia">function minkowskiquestionmark(x)
y, p = Int(floorfldmod(x), 1)
(xq, >d = 1 || x < 0) && return- p, + minkowski(x).5
q,while r, s, m, n = 1, py + 1, 1,d 0,> 0y
d, y p < q ? (q -= 1.0,p) : Float64(p -= q; y += d)
while true d /= 2
d /= 2.0
y + d == y && break
m = p + r
(m < 0 || p < 0) && break
n = q + s
n < 0 && break
if x < (m / n)
r, s = m, n
else
y, p, q = y + d, m, n
end
end
return y + d
end
 
function minkowski_invquestionmark_inv(x, maxiter=151)
py, bits = Int(floorfldmod(x), 1)
lo, hi = [0, 1], [1, 1]
(x > 1 || x < 0) && return p + minkowski_inv(x - p, maxiter)
while (xy ==+ 1/(lo...)) ||< x(y ==+ 0/(hi...)) && return x
bit, bits = fldmod(2bits, 1)
contfrac = [0]
bit > 0 ? (lo .+= hi) : (hi .+= lo)
curr, coun, i = 0, 1, 0
while i < maxiter
x *= 2
if curr == 0
if x < 1
coun += 1
else
i += 1
push!(contfrac, 0)
contfrac[i] = coun
coun = 1
curr = 1
x -= 1
end
else
if x > 1
coun += 1
x -= 1
else
i += 1
push!(contfrac, 0)
contfrac[i] = coun
coun = 1
curr = 0
end
end
if x == Int(floor(x))
contfrac[i + 1] = coun
break
end
end
rety =+ 1/(lo.0 / contfrac[i + 1]..)
for j in i:-1:1
ret = contfrac[j] + 1.0 / ret
end
return 1.0 / ret
end
 
x, y = 0.7182818281828, 0.1213141516171819
println(" ", minkowski((1 + sqrt(5)) / 2), " ", 5 / 3)
for (a, b) ∈ [
println(minkowski_inv(-5/9), " ", (sqrt(13) - 7) / 6)
(5/3, questionmark((1 + √5)/2)),
println(" ", minkowski(minkowski_inv(0.718281828)), " ",
((√13-7)/6, questionmark_inv(-5/9)),
minkowski_inv(minkowski(0.1213141516171819)))
(x, questionmark_inv(questionmark(x))),
</lang>{{out}}
(y, questionmark(questionmark_inv(y)))]
println(a, a ≈ b ? " ≈ " : " != ", b)
end
</syntaxhighlight>{{out}}
<pre>
1.6666666666666667 ≈ 1.666666666667894
1.6666666666696983 1.6666666666666667
-0.5657414540893352 ≈ -0.5657414540893351
-0.5657414540893351 -0.5657414540893352
0.7182818281828 ≈ 0.7182818281828183
0.7182818280000092 0.12131415161718191
0.1213141516171819 ≈ 0.12131415161718095
</pre>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">ClearAll[InverseMinkowskiQuestionMark]
InverseMinkowskiQuestionMark[val_] := Module[{x}, (x /. FindRoot[MinkowskiQuestionMark[x] == val, {x, Floor[val], Ceiling[val]}])]
MinkowskiQuestionMark[GoldenRatio]
InverseMinkowskiQuestionMark[-5/9] // RootApproximant
MinkowskiQuestionMark[InverseMinkowskiQuestionMark[0.1213141516171819]]
InverseMinkowskiQuestionMark[MinkowskiQuestionMark[0.1213141516171819]]</langsyntaxhighlight>
{{out}}
<pre>5/3
Line 618 ⟶ 987:
=={{header|Nim}}==
{{trans|Go}}
<langsyntaxhighlight Nimlang="nim">import math, strformat
 
const MaxIter = 151
Line 704 ⟶ 1,073:
echo &"{minkowskiInv(-5/9):19.16f}, {(sqrt(13.0)-7)/6:19.16f}"
echo &"{minkowski(minkowskiInv(0.718281828)):19.16f}, " &
&"{minkowskiInv(minkowski(0.1213141516171819)):19.16f}"</langsyntaxhighlight>
 
{{out}}
Line 713 ⟶ 1,082:
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
Line 780 ⟶ 1,149:
printf "%19.16f %19.16f\n", minkowski(0.5*(1 + sqrt(5))), 5/3;
printf "%19.16f %19.16f\n", minkowskiInv(-5/9), (sqrt(13)-7)/6;
printf "%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)), minkowskiInv(minkowski(0.1213141516171819));</langsyntaxhighlight>
{{out}}
<pre> 1.6666666666696983 1.6666666666666667
Line 788 ⟶ 1,157:
=={{header|Phix}}==
{{trans|FreeBASIC}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Euphoria>constant MAXITER = 151
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">MAXITER</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">151</span>
function minkowski(atom x)
atom p = floor(x)
<span style="color: #008080;">function</span> <span style="color: #000000;">minkowski</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
if x>1 or x<0 then return p+minkowski(x-p) end if
<span style="color: #004080;">atom</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
atom q = 1, r = p + 1, s = 1, m, n, d = 1, y = p
<span style="color: #008080;">if</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #000000;">x</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">+</span><span style="color: #000000;">minkowski</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">-</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
while true do
<span style="color: #004080;">atom</span> <span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p</span>
d = d/2
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
if y + d = y then exit end if
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span>
m = p + r
<span style="color: #008080;">if</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if m < 0 or p < 0 then exit end if
<span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">r</span>
n = q + s
<span style="color: #008080;">if</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if n < 0 then exit end if
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">q</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">s</span>
if x < m/n then
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
r = m
<span style="color: #008080;">if</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">/</span><span style="color: #000000;">n</span> <span style="color: #008080;">then</span>
s = n
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m</span>
else
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span>
y = y + d
<span p style="color: m#008080;">else</span>
<span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">d</span>
q = n
<span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m</span>
end if
<span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return y + d
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">d</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function minkowski_inv(atom x)
if x>1 or x<0 then return floor(x)+minkowski_inv(x-floor(x)) end if
<span style="color: #008080;">function</span> <span style="color: #000000;">minkowski_inv</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
if x=1 or x=0 then return x end if
<span style="color: #008080;">if</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #000000;">x</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">minkowski_inv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">-</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
sequence contfrac = {}
<span style="color: #008080;">if</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">x</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer curr = 0, count = 1
<span style="color: #004080;">sequence</span> <span style="color: #000000;">contfrac</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
while true do
<span style="color: #004080;">integer</span> <span style="color: #000000;">curr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
x *= 2
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
if curr = 0 then
<span style="color: #000000;">x</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">2</span>
if x<1 then
<span style="color: #008080;">if</span> <span style="color: #000000;">curr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
count += 1
<span style="color: #008080;">if</span> <span style="color: #000000;">x</span><span style="color: #0000FF;"><</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
contfrac &= count
<span count style="color: 1#008080;">else</span>
<span style="color: #000000;">contfrac</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">count</span>
curr = 1
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
x -= 1
<span style="color: #000000;">curr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
end if
<span style="color: #000000;">x</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
else
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if x>1 then
<span count +style="color: 1#008080;">else</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
x -= 1
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
else
<span style="color: #000000;">x</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
contfrac &= count
<span count style="color: 1#008080;">else</span>
<span style="color: #000000;">contfrac</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">count</span>
curr = 0
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
end if
<span style="color: #000000;">curr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if x = floor(x) then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
contfrac &= count
<span style="color: #008080;">if</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
exit
<span style="color: #000000;">contfrac</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">count</span>
end if
<span style="color: #008080;">exit</span>
if length(contfrac)=MAXITER then exit end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end while
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">contfrac</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">MAXITER</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
atom ret = 1/contfrac[$]
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
for i = length(contfrac)-1 to 1 by -1 do
<span style="color: #004080;">atom</span> <span style="color: #000000;">ret</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">contfrac</span><span style="color: #0000FF;">[$]</span>
ret = contfrac[i] + 1.0/ret
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">contfrac</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">ret</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">contfrac</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1.0</span><span style="color: #0000FF;">/</span><span style="color: #000000;">ret</span>
return 1/ret
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">ret</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
printf(1,"%20.16f %20.16f\n",{minkowski(0.5*(1+sqrt(5))), 5/3})
printf(1,"%20.16f %20.16f\n",{minkowski_inv(-5/9), (sqrt(13)-7)/6})
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%20.16f %20.16f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">minkowski</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">+</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">))),</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">})</span>
printf(1,"%20.16f %20.16f\n",{minkowski(minkowski_inv(0.718281828)),
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%20.16f %20.16f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">minkowski_inv</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">/</span><span style="color: #000000;">9</span><span style="color: #0000FF;">),</span> <span style="color: #0000FF;">(</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">13</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">7</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">6</span><span style="color: #0000FF;">})</span>
minkowski_inv(minkowski(0.1213141516171819))})</lang>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%20.16f %20.16f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">minkowski</span><span style="color: #0000FF;">(</span><span style="color: #000000;">minkowski_inv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.718281828</span><span style="color: #0000FF;">)),</span>
<span style="color: #000000;">minkowski_inv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">minkowski</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.1213141516171819</span><span style="color: #0000FF;">))})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 865 ⟶ 1,237:
=={{header|Python}}==
{{trans|Go}}
<langsyntaxhighlight lang="python">import math
 
MAXITER = 151
Line 978 ⟶ 1,350:
)
)
</syntaxhighlight>
</lang>
 
{{out}}
Line 989 ⟶ 1,361:
=={{header|Raku}}==
{{trans|Go}}
<syntaxhighlight lang="raku" perl6line># 20201120 Raku programming solution
 
my \MAXITER = 151;
Line 1,053 ⟶ 1,425:
printf "%19.16f %19.16f\n", minkowskiInv(-5/9), (13.sqrt-7)/6;
printf "%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)),
minkowskiInv(minkowski(0.1213141516171819))</langsyntaxhighlight>
{{out}}
<pre> 1.6666666666696983 1.6666666666666667
Line 1,062 ⟶ 1,434:
{{trans|FreeBASIC}}
{{trans|Phix}}
<langsyntaxhighlight lang="rexx">/*REXX program uses the Minkowski question─mark function to convert a continued fraction*/
numeric digits 40 /*use enough dec. digits for precision.*/
say fmt( mink( 0.5 * (1+sqrt(5) ) ) ) fmt( 5/3 )
Line 1,103 ⟶ 1,475:
numeric form; m.=9; parse value format(x,2,1,,0) 'E0' with g "E" _ .; g=g *.5'e'_ %2
do j=0 while h>9; m.j= h; h= h % 2 + 1; end /*j*/
do k=j+5 to 0 by -1; numeric digits m.k; g= (g + x/g) * .5; end /*k*/; return g</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the internal default inputs:}}
<pre>
Line 1,114 ⟶ 1,486:
{{trans|FreeBASIC}}
{{libheader|Wren-fmt}}
<langsyntaxhighlight ecmascriptlang="wren">import "./fmt" for Fmt
 
var MAXITER = 151
Line 1,197 ⟶ 1,569:
Fmt.print("$17.14f $17.14f", minkowskiInv.call(-5/9), (13.sqrt - 7)/6)
Fmt.print("$17.14f $17.14f", minkowski.call(minkowskiInv.call(0.718281828)),
minkowskiInv.call(minkowski.call(0.1213141516171819)))</langsyntaxhighlight>
 
{{out}}
337

edits