69 lines
1.7 KiB
Perl
69 lines
1.7 KiB
Perl
use strict;
|
|
use warnings;
|
|
use feature 'say';
|
|
use POSIX qw(floor);
|
|
|
|
my $MAXITER = 50;
|
|
|
|
sub minkowski {
|
|
my($x) = @_;
|
|
|
|
return floor($x) + minkowski( $x - floor($x) ) if $x > 1 || $x < 0 ;
|
|
|
|
my $y = my $p = floor($x);
|
|
my ($q,$s,$d) = (1,1,1);
|
|
my $r = $p + 1;
|
|
|
|
while () {
|
|
last if ( $y + ($d /= 2) == $y ) or
|
|
( my $m = $p + $r) < 0 or
|
|
( my $n = $q + $s) < 0;
|
|
$x < $m/$n ? ($r,$s) = ($m, $n) : ($y += $d and ($p,$q) = ($m, $n) );
|
|
}
|
|
return $y + $d
|
|
}
|
|
|
|
sub minkowskiInv {
|
|
my($x) = @_;
|
|
|
|
return floor($x) + minkowskiInv($x - floor($x)) if $x > 1 || $x < 0;
|
|
return $x if $x == 1 || $x == 0 ;
|
|
|
|
my @contFrac = 0;
|
|
my $i = my $curr = 0 ; my $count = 1;
|
|
|
|
while () {
|
|
$x *= 2;
|
|
if ($curr == 0) {
|
|
if ($x < 1) {
|
|
$count++
|
|
} else {
|
|
$i++;
|
|
push @contFrac, 0;
|
|
$contFrac[$i-1] = $count;
|
|
($count,$curr) = (1,1);
|
|
$x--;
|
|
}
|
|
} else {
|
|
if ($x > 1) {
|
|
$count++;
|
|
$x--;
|
|
} else {
|
|
$i++;
|
|
push @contFrac, 0;
|
|
@contFrac[$i-1] = $count;
|
|
($count,$curr) = (1,0);
|
|
}
|
|
}
|
|
if ($x == floor($x)) { @contFrac[$i] = $count; last }
|
|
last if $i == $MAXITER;
|
|
}
|
|
my $ret = 1 / $contFrac[$i];
|
|
for (my $j = $i - 1; $j >= 0; $j--) { $ret = $contFrac[$j] + 1/$ret }
|
|
return 1 / $ret
|
|
}
|
|
|
|
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));
|