Minkowski question-mark function: Difference between revisions

Content added Content deleted
m (syntax highlighting fixup automation)
Line 30: Line 30:
{{trans|Python}}
{{trans|Python}}


<lang 11l>-V MAXITER = 151
<syntaxhighlight lang="11l">-V MAXITER = 151


F minkowski(x) -> Float
F minkowski(x) -> Float
Line 119: 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(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_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))))</lang>
print(‘#2.16 #2.16’.format(minkowski(minkowski_inv(0.718281828)), minkowski_inv(minkowski(0.1213141516171819))))</syntaxhighlight>


{{out}}
{{out}}
Line 130: Line 130:
=={{header|Factor}}==
=={{header|Factor}}==
{{works with|Factor|0.99 2020-08-14}}
{{works with|Factor|0.99 2020-08-14}}
<lang factor>USING: formatting kernel make math math.constants
<syntaxhighlight lang="factor">USING: formatting kernel make math math.constants
math.continued-fractions math.functions math.parser
math.continued-fractions math.functions math.parser
math.statistics sequences sequences.extras splitting.monotonic
math.statistics sequences sequences.extras splitting.monotonic
Line 165: Line 165:
phi ? 5 3 /f compare
phi ? 5 3 /f compare
-5/9 ?⁻¹ 13 sqrt 7 - 6 /f compare
-5/9 ?⁻¹ 13 sqrt 7 - 6 /f compare
0.718281828 ?⁻¹ ? 0.1213141516171819 ? ?⁻¹ compare</lang>
0.718281828 ?⁻¹ ? 0.1213141516171819 ? ?⁻¹ compare</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 175: Line 175:
=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==


<lang freebasic>#define MAXITER 151
<syntaxhighlight lang="freebasic">#define MAXITER 151


function minkowski( x as double ) as double
function minkowski( x as double ) as double
Line 246: Line 246:
print minkowski_inv( -5./9 ), (sqr(13)-7)/6
print minkowski_inv( -5./9 ), (sqr(13)-7)/6
print minkowski(minkowski_inv(0.718281828)), minkowski_inv(minkowski(0.1213141516171819))
print minkowski(minkowski_inv(0.718281828)), minkowski_inv(minkowski(0.1213141516171819))
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre> 1.666666666669698 1.666666666666667
<pre> 1.666666666669698 1.666666666666667
Line 254: Line 254:
=={{header|Go}}==
=={{header|Go}}==
{{trans|FreeBASIC}}
{{trans|FreeBASIC}}
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 358: Line 358:
fmt.Printf("%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)),
fmt.Printf("%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)),
minkowskiInv(minkowski(0.1213141516171819)))
minkowskiInv(minkowski(0.1213141516171819)))
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 376: Line 376:
This recursive definition can be implemented as lazy corecursion, i.e. by generating two infinite binary trees: '''mediant'''-based Stern-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).
This recursive definition can be implemented as lazy corecursion, i.e. by generating two infinite binary trees: '''mediant'''-based Stern-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).


<lang haskell>import Data.Tree
<syntaxhighlight lang="haskell">import Data.Tree
import Data.Ratio
import Data.Ratio
import Data.List
import Data.List
Line 431: Line 431:
questionMarkF, invQuestionMarkF :: Double -> Double
questionMarkF, invQuestionMarkF :: Double -> Double
questionMarkF = sternBrocotF ==> minkowskiF
questionMarkF = sternBrocotF ==> minkowskiF
invQuestionMarkF = minkowskiF ==> sternBrocotF</lang>
invQuestionMarkF = minkowskiF ==> sternBrocotF</syntaxhighlight>


<pre>λ> mapM_ print $ take 4 $ levels farey
<pre>λ> mapM_ print $ take 4 $ levels farey
Line 469: Line 469:
Implementation:
Implementation:


<lang J>ITERCOUNT=: 52
<syntaxhighlight lang="j">ITERCOUNT=: 52


minkowski=: {{
minkowski=: {{
Line 499: Line 499:
end.
end.
(+%)/(<.y),cf
(+%)/(<.y),cf
}}</lang>
}}</syntaxhighlight>


That said, note that this algorithm introduces significant numeric instability for √7 divided by 3:
That said, note that this algorithm introduces significant numeric instability for √7 divided by 3:


<lang J> (minkowski@invmink - invmink@minkowski) (p:%%:)3
<syntaxhighlight lang="j"> (minkowski@invmink - invmink@minkowski) (p:%%:)3
1.10713e_6</lang>
1.10713e_6</syntaxhighlight>


I see this same instability using the python implementation and appending:
I see this same instability using the python implementation and appending:


<lang python> print(
<syntaxhighlight lang="python"> print(
"{:19.16f} {:19.16f}".format(
"{:19.16f} {:19.16f}".format(
minkowski(minkowski_inv(4.04145188432738056)),
minkowski(minkowski_inv(4.04145188432738056)),
minkowski_inv(minkowski(4.04145188432738056)),
minkowski_inv(minkowski(4.04145188432738056)),
)
)
)</lang>
)</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.
Using an exact fraction for 4.04145188432738056 and bumping the iteration count from 52 up to 200 changes that difference to 1.43622e_12.
Line 519: Line 519:
=={{header|Julia}}==
=={{header|Julia}}==
{{trans|FreeBASIC}}
{{trans|FreeBASIC}}
<lang julia>function minkowski(x)
<syntaxhighlight lang="julia">function minkowski(x)
p = Int(floor(x))
p = Int(floor(x))
(x > 1 || x < 0) && return p + minkowski(x)
(x > 1 || x < 0) && return p + minkowski(x)
Line 587: Line 587:
println(" ", minkowski(minkowski_inv(0.718281828)), " ",
println(" ", minkowski(minkowski_inv(0.718281828)), " ",
minkowski_inv(minkowski(0.1213141516171819)))
minkowski_inv(minkowski(0.1213141516171819)))
</lang>{{out}}
</syntaxhighlight>{{out}}
<pre>
<pre>
1.6666666666696983 1.6666666666666667
1.6666666666696983 1.6666666666666667
Line 595: Line 595:


=={{header|Mathematica}} / {{header|Wolfram Language}}==
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<lang Mathematica>ClearAll[InverseMinkowskiQuestionMark]
<syntaxhighlight lang="mathematica">ClearAll[InverseMinkowskiQuestionMark]
InverseMinkowskiQuestionMark[val_] := Module[{x}, (x /. FindRoot[MinkowskiQuestionMark[x] == val, {x, Floor[val], Ceiling[val]}])]
InverseMinkowskiQuestionMark[val_] := Module[{x}, (x /. FindRoot[MinkowskiQuestionMark[x] == val, {x, Floor[val], Ceiling[val]}])]
MinkowskiQuestionMark[GoldenRatio]
MinkowskiQuestionMark[GoldenRatio]
InverseMinkowskiQuestionMark[-5/9] // RootApproximant
InverseMinkowskiQuestionMark[-5/9] // RootApproximant
MinkowskiQuestionMark[InverseMinkowskiQuestionMark[0.1213141516171819]]
MinkowskiQuestionMark[InverseMinkowskiQuestionMark[0.1213141516171819]]
InverseMinkowskiQuestionMark[MinkowskiQuestionMark[0.1213141516171819]]</lang>
InverseMinkowskiQuestionMark[MinkowskiQuestionMark[0.1213141516171819]]</syntaxhighlight>
{{out}}
{{out}}
<pre>5/3
<pre>5/3
Line 609: Line 609:
=={{header|Nim}}==
=={{header|Nim}}==
{{trans|Go}}
{{trans|Go}}
<lang Nim>import math, strformat
<syntaxhighlight lang="nim">import math, strformat


const MaxIter = 151
const MaxIter = 151
Line 695: Line 695:
echo &"{minkowskiInv(-5/9):19.16f}, {(sqrt(13.0)-7)/6:19.16f}"
echo &"{minkowskiInv(-5/9):19.16f}, {(sqrt(13.0)-7)/6:19.16f}"
echo &"{minkowski(minkowskiInv(0.718281828)):19.16f}, " &
echo &"{minkowski(minkowskiInv(0.718281828)):19.16f}, " &
&"{minkowskiInv(minkowski(0.1213141516171819)):19.16f}"</lang>
&"{minkowskiInv(minkowski(0.1213141516171819)):19.16f}"</syntaxhighlight>


{{out}}
{{out}}
Line 704: Line 704:
=={{header|Perl}}==
=={{header|Perl}}==
{{trans|Raku}}
{{trans|Raku}}
<lang perl>use strict;
<syntaxhighlight lang="perl">use strict;
use warnings;
use warnings;
use feature 'say';
use feature 'say';
Line 771: Line 771:
printf "%19.16f %19.16f\n", minkowski(0.5*(1 + sqrt(5))), 5/3;
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", minkowskiInv(-5/9), (sqrt(13)-7)/6;
printf "%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)), minkowskiInv(minkowski(0.1213141516171819));</lang>
printf "%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)), minkowskiInv(minkowski(0.1213141516171819));</syntaxhighlight>
{{out}}
{{out}}
<pre> 1.6666666666696983 1.6666666666666667
<pre> 1.6666666666696983 1.6666666666666667
Line 779: Line 779:
=={{header|Phix}}==
=={{header|Phix}}==
{{trans|FreeBASIC}}
{{trans|FreeBASIC}}
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<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>
<span style="color: #008080;">constant</span> <span style="color: #000000;">MAXITER</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">151</span>
Line 849: Line 849:
<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: #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>
<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>
<!--</lang>-->
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 859: Line 859:
=={{header|Python}}==
=={{header|Python}}==
{{trans|Go}}
{{trans|Go}}
<lang python>import math
<syntaxhighlight lang="python">import math


MAXITER = 151
MAXITER = 151
Line 972: Line 972:
)
)
)
)
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 983: Line 983:
=={{header|Raku}}==
=={{header|Raku}}==
{{trans|Go}}
{{trans|Go}}
<lang perl6># 20201120 Raku programming solution
<syntaxhighlight lang="raku" line># 20201120 Raku programming solution


my \MAXITER = 151;
my \MAXITER = 151;
Line 1,047: Line 1,047:
printf "%19.16f %19.16f\n", minkowskiInv(-5/9), (13.sqrt-7)/6;
printf "%19.16f %19.16f\n", minkowskiInv(-5/9), (13.sqrt-7)/6;
printf "%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)),
printf "%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)),
minkowskiInv(minkowski(0.1213141516171819))</lang>
minkowskiInv(minkowski(0.1213141516171819))</syntaxhighlight>
{{out}}
{{out}}
<pre> 1.6666666666696983 1.6666666666666667
<pre> 1.6666666666696983 1.6666666666666667
Line 1,056: Line 1,056:
{{trans|FreeBASIC}}
{{trans|FreeBASIC}}
{{trans|Phix}}
{{trans|Phix}}
<lang rexx>/*REXX program uses the Minkowski question─mark function to convert a continued fraction*/
<syntaxhighlight lang="rexx">/*REXX program uses the Minkowski question─mark function to convert a continued fraction*/
numeric digits 40 /*use enough dec. digits for precision.*/
numeric digits 40 /*use enough dec. digits for precision.*/
say fmt( mink( 0.5 * (1+sqrt(5) ) ) ) fmt( 5/3 )
say fmt( mink( 0.5 * (1+sqrt(5) ) ) ) fmt( 5/3 )
Line 1,097: Line 1,097:
numeric form; m.=9; parse value format(x,2,1,,0) 'E0' with g "E" _ .; g=g *.5'e'_ %2
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 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</lang>
do k=j+5 to 0 by -1; numeric digits m.k; g= (g + x/g) * .5; end /*k*/; return g</syntaxhighlight>
{{out|output|text=&nbsp; when using the internal default inputs:}}
{{out|output|text=&nbsp; when using the internal default inputs:}}
<pre>
<pre>
Line 1,108: Line 1,108:
{{trans|FreeBASIC}}
{{trans|FreeBASIC}}
{{libheader|Wren-fmt}}
{{libheader|Wren-fmt}}
<lang ecmascript>import "/fmt" for Fmt
<syntaxhighlight lang="ecmascript">import "/fmt" for Fmt


var MAXITER = 151
var MAXITER = 151
Line 1,191: Line 1,191:
Fmt.print("$17.14f $17.14f", minkowskiInv.call(-5/9), (13.sqrt - 7)/6)
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)),
Fmt.print("$17.14f $17.14f", minkowski.call(minkowskiInv.call(0.718281828)),
minkowskiInv.call(minkowski.call(0.1213141516171819)))</lang>
minkowskiInv.call(minkowski.call(0.1213141516171819)))</syntaxhighlight>


{{out}}
{{out}}