Re: [QUIZ] Perl 'Easy' Quiz of the Week #2006-04-02 - Rounded Fractions
"Kester Allen" <[email protected]> Thu, 6 Apr 2006 09:42:16 -0700
| Newsgroups | gmane.comp.lang.perl.qotw.discuss |
|---|---|
| Message-ID | <[email protected]> |
Here's my solution:
#!/usr/bin/perl
use strict;
use warnings;
eval {
main ();
};
if ( my $err =3D $@ ) {
print STDERR "# $0: $err\n";
exit 1 ;
}
exit 0;
sub main {
my $in_frac1 =3D shift @ARGV or die "need two inputs";
my $in_frac2 =3D shift @ARGV or die "need two inputs";
my $dec1 =3D frac2dec( $in_frac1 );
my $dec2 =3D frac2dec( $in_frac2 );
my $frac =3D dec2frac( $dec1 * $dec2 );
print "$in_frac1 X $in_frac2 =3D $frac\n",
"$dec1 X $dec2 =3D ", $dec1 * $dec2, "\n";
}
sub dec2frac {
my $dec =3D shift () or die "no input in dec2frac";
my $intpart =3D int $dec;
# We need to round to the closest 1/4, 1/3, or 1/2. Convert
# the fraction into x/12, and then simplify the fraction:
#
my $denom =3D 12;
my $neum =3D int ( $denom * ($dec - $intpart) + 0.5 ); #rounding
foreach my $div ( 2, 3 ) {
while( 0 =3D=3D $neum % $div ) {
$neum /=3D $div;
$denom /=3D $div;
}
}
return "$intpart $neum / $denom";
}
sub frac2dec {
my $frac =3D shift () or die "no input in frac2dec";
# strip leading and trailing whitespace
#
$frac =3D~ s/^\s+|\s+$//g;
# Split the fraction on slashes surrounded by zero-or-more whitespaces,=
or
# whitespaces themselves. This split should produce an array with ei=
ther
# one (just a number), two (for a pure fraction), or three (for a
# number-plus-fraction) elements:
#
my @frac_decomp =3D split /\s*\/\s*|\s+/, $frac;
my ( $prop, $neumerator, $denomenator )
=3D ( scalar @frac_decomp =3D=3D 3 ) ? @frac_decomp
: ( scalar @frac_decomp =3D=3D 2 ) ? ( 0, @frac_decomp[0,1] )
: ( scalar @frac_decomp =3D=3D 1 ) ? ( $frac_decomp[0], 0, 1 )
: die "input is bad: \"@frac_decomp\"";
# Return the decimal value:
#
return $prop + $neumerator / $denomenator;
}