diff options
| author | PerlMonk Athanasius <PerlMonk.Athanasius@gmail.com> | 2019-08-18 09:08:33 -0700 |
|---|---|---|
| committer | PerlMonk Athanasius <PerlMonk.Athanasius@gmail.com> | 2019-08-18 09:08:33 -0700 |
| commit | 5fca3a1558a0ec813dd2ad87281fe2bd440a259c (patch) | |
| tree | 4891e1b28dcee96d3dd6c19d0309811e77fdeb29 /challenge-021 | |
| parent | dfbe68baaeae58970920eb44fb1f18a9d796eb02 (diff) | |
| download | perlweeklychallenge-club-5fca3a1558a0ec813dd2ad87281fe2bd440a259c.tar.gz perlweeklychallenge-club-5fca3a1558a0ec813dd2ad87281fe2bd440a259c.tar.bz2 perlweeklychallenge-club-5fca3a1558a0ec813dd2ad87281fe2bd440a259c.zip | |
Perl 5 & 6 solutions to Task 1 of Challenge #021
Changes to be committed:
new file: challenge-021/athanasius/perl5/ch-1.pl
new file: challenge-021/athanasius/perl6/ch-1.p6
Diffstat (limited to 'challenge-021')
| -rw-r--r-- | challenge-021/athanasius/perl5/ch-1.pl | 96 | ||||
| -rw-r--r-- | challenge-021/athanasius/perl6/ch-1.p6 | 67 |
2 files changed, 163 insertions, 0 deletions
diff --git a/challenge-021/athanasius/perl5/ch-1.pl b/challenge-021/athanasius/perl5/ch-1.pl new file mode 100644 index 0000000000..42796cdb3f --- /dev/null +++ b/challenge-021/athanasius/perl5/ch-1.pl @@ -0,0 +1,96 @@ +#!perl + +################################################################################ +=comment + +Perl Weekly Challenge 021 +========================= + +Task #1 +------- +Write a script to calculate the value of *e*, also known as *Euler's number* and +*Napier's constant*. Please checkout wiki [ https://en.wikipedia.org/wiki/ +E_(mathematical_constant) |page] for more information. + +=cut +################################################################################ + +#--------------------------------------# +# Copyright © 2019 PerlMonk Athanasius # +#--------------------------------------# + +use strict; +use warnings; +use bignum; +use Const::Fast; +use Getopt::Long; + +const my $PRECISION => 50; +const my $USAGE => "USAGE: perl $0 [--precision <UInt>]\n"; + +BEGIN +{ + print "\n"; +} + +MAIN: +{ + my $precision = $PRECISION; + + GetOptions + ( + 'precision=i' => \$precision, + + ) or die $USAGE; + + $precision >= 0 + or die "Invalid precision \"$precision\"\n$USAGE"; + + my $accuracy = $precision + 3; + + Math::BigFloat->accuracy($accuracy); + + my $e_prev = Math::BigFloat->bone('-');; + my $e_next = Math::BigFloat->bzero; + my $n = 0; + + while ($e_prev->blt($e_next)) + { + $e_prev = $e_next->copy; + my $d = $n++ * 2; + $e_next->badd( ($d + 2) / factorial($d + 1) ); + } + + --$n; + $accuracy -= 2; + my $e_truncated = $e_next->copy->bround($accuracy, 'trunc'); + my $e_rounded = $e_next->copy->bround($accuracy, 'even'); + + print "After $n steps of the H J Brothers convergence series,\n", + " e = ", $e_truncated, " (truncated)\n", + "or e = ", $e_rounded, " (rounded)\n", + "with a precision of $precision decimal place", + ($precision == 1 ? '' : 's'), ".\n"; +} + +sub factorial +{ + my ($n) = @_; + my $f = 1; + $f *= $_ for 2 .. $n; + + return $f; +} + +################################################################################ + +__END__ + +The H J Brothers convergence series: + +e = Sum[n = 0 .. Inf] ( (2n + 2) / (2n + 1)! ) + +References: + +-- https://www.intmath.com/exponential-logarithmic-functions/calculating-e.php +-- http://www.brotherstechnology.com/docs/icnsae_(cmj0104-300dpi).pdf diff --git a/challenge-021/athanasius/perl6/ch-1.p6 b/challenge-021/athanasius/perl6/ch-1.p6 new file mode 100644 index 0000000000..12095892b1 --- /dev/null +++ b/challenge-021/athanasius/perl6/ch-1.p6 @@ -0,0 +1,67 @@ +use v6; + +################################################################################ +=begin comment + +Perl Weekly Challenge 021 +========================= + +Task #1 +------- +Write a script to calculate the value of *e*, also known as *Euler's number* and +*Napier's constant*. Please checkout wiki [ https://en.wikipedia.org/wiki/ +E_(mathematical_constant) |page] for more information. + +=end comment +################################################################################ + +#--------------------------------------# +# Copyright © 2019 PerlMonk Athanasius # +#--------------------------------------# + +my UInt constant $PRECISION = 50; +my UInt constant $MARGIN = 5; # Additional precision to ensure that the + # convergence calculations are correct + +BEGIN say ''; + +#------------------------------------------------------------------------------- +# For the use of FatRat, see brian d foy, "As Many Digits as You Like," +# https://www.learningperl6.com/2017/04/24/as-many-digits-as-you-like/ +#------------------------------------------------------------------------------- + +sub MAIN(UInt:D :$precision = $PRECISION) +{ + my FatRat $e = FatRat.new(0, 1); + my UInt $target = $precision + 2 + $MARGIN; # "+ 2" is for leading "2." + my UInt $n = 0; + + while $e.Str.chars <= $target + { + my UInt $d = $n++ * 2; + + $e += ($d + 2).FatRat / factorial($d + 1); + } + + --$n; + my Str $e-truncated = $e.substr(0 .. ($precision + 1)); + $e-truncated = $e-truncated.chop if $e-truncated.chars == 2; + my FatRat $unit = FatRat.new(1, 10 ** $precision); + my Str $e-rounded = $e.round($unit).Str; + + say "After $n steps of the H J Brothers convergence series,\n", + " e = ", $e-truncated, " (truncated)\n", + "or e = ", $e-rounded, " (rounded)\n", + "with a precision of $precision decimal place", + ($precision == 1 ?? '.' !! 's.'); +} + +sub factorial(UInt:D $n --> UInt:D) +{ + my UInt $f = 1; + $f *= $_ for 2 .. $n; + + return $f; +} + +################################################################################ |
