Ott 282009
 
#!/usr/bin/perl

use strict;
use warnings;
use Math::BigInt;
use Math::BigFloat;
use feature ':5.10';

main();

sub reduce {
    my ( $function, $init, @list ) = @_;
    my $value = $init;
    foreach my $item ( @list ) {    
        $value = $function->($value, $item);
    }
    return $value;
}

sub approximants {
return reduce(
    sub {
        my ( $a1, $a2 ) = @_;
        $a2 = Math::BigInt->new( $a2 )
            if ref $a2 ne 'Math::BigInt';
        my $v = [ $a2 * $a1->[0] + $a1->[2],
                  $a2 * $a1->[1] + $a1->[3],
                  $a1->[0],
                  $a1->[1] ];
        printf "%5.5s : %34.34s/%-34.34s = %-42.42sn",
                $a2,
                $v->[0],
                $v->[1],
                Math::BigFloat->new($v->[0])
                / Math::BigFloat->new($v->[1]),
        ;
        return $v;
    },
    [ Math::BigInt->bone,
      Math::BigInt->bzero,
      Math::BigInt->bzero,
      Math::BigInt->bone ],
        @_
    );
}

sub continued_fraction {
    my ( $r, $limit ) = @_;
    $r = Math::BigFloat->new($r)
        if ref $r ne 'Math::BigFloat';
    my $epsilon = Math::BigFloat->new('1.0e-20');
    my @cf;
    foreach ( 1 .. $limit ) {
        my $i = int $r;
        push @cf, $i;
        last if ($r - $i) < $epsilon;
        $r = Math::BigFloat->bone / ( $r - $i );
    }
    return wantarray ? @cf : @cf;
}

sub show_continued_fraction {
    my ( $value, @array ) = @_;
    printf "%-42.42s %sn",
        $value,
        ' = [' . join( ', ', @array ) . ']';
    return;
}

sub main {

    Math::BigFloat->accuracy(100);

    my $v = Math::BigFloat->bone->bexp;
    my @cf = continued_fraction( $v, 50 );
    show_continued_fraction( $v, @cf );
    approximants( @cf );
}

Sorry, the comment form is closed at this time.