aboutsummaryrefslogtreecommitdiff
path: root/challenge-021
diff options
context:
space:
mode:
authorPerlMonk Athanasius <PerlMonk.Athanasius@gmail.com>2019-08-18 09:08:33 -0700
committerPerlMonk Athanasius <PerlMonk.Athanasius@gmail.com>2019-08-18 09:08:33 -0700
commit5fca3a1558a0ec813dd2ad87281fe2bd440a259c (patch)
tree4891e1b28dcee96d3dd6c19d0309811e77fdeb29 /challenge-021
parentdfbe68baaeae58970920eb44fb1f18a9d796eb02 (diff)
downloadperlweeklychallenge-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.pl96
-rw-r--r--challenge-021/athanasius/perl6/ch-1.p667
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;
+}
+
+################################################################################