| Math-Cephes documentation | Contained in the Math-Cephes distribution. |
Math::Cephes::Fraction - Perl interface to the cephes math fraction routines
use Math::Cephes::Fraction qw(fract); my $f1 = fract(2,3); # $f1 = 2/3 my $f2 = fract(3,4); # $f2 = 3/4 my $f3 = $f1->radd($f2); # $f3 = $f1 + $f2
This module is a layer on top of the basic routines in the cephes math library to handle fractions. A fraction object is created via any of the following syntaxes:
my $f = Math::Cephes::Fraction->new(3, 2); # $f = 3/2 my $g = new Math::Cephes::Fraction(5, 3); # $g = 5/3 my $h = fract(7, 5); # $h = 7/5
the last one being available by importing :fract. If no arguments are specified, as in
my $h = fract();
then the defaults $z = 0/1 are assumed. The numerator and denominator of a fraction are represented respectively by
$f->{n}; $f->{d}
or, as methods,
$f->n; $f->d;
and can be set according to
$f->{n} = 4; $f->{d} = 9;
or, again, as methods,
$f->n(4) ; $f->(d) = 9;
The fraction can be printed out as
print $f->as_string;
or as a mixed fraction as
print $f->as_mixed_string;
These routines reduce the fraction to its basic form before printing. This uses the euclid routine which finds the greatest common divisor of two numbers, as follows:
($gcd, $m_reduced, $n_reduced) = euclid($m, $n);
which returns the greatest common divisor of $m and $n, as well as the result of reducing $m and $n by $gcd
A summary of the basic routines is as follows.
$x = fract(3, 4); # x = 3 / 4
$y = fract(2, 3); # y = 2 / 3
$z = $x->radd( $y ); # z = x + y
$z = $x->rsub( $y ); # z = x - y
$z = $x->rmul( $y ); # z = x * y
$z = $x->rdiv( $y ); # z = x / y
print $z->{n}, ' ', $z->{d}; # prints numerator and denominator of $z
print $z->as_string; # prints the fraction $z
print $z->as_mixed_string; # converts $z to a mixed fraction, then prints it
$m = 60;
$n = 144;
($gcd, $m_reduced, $n_reduced) = euclid($m, $n);
Please report any to Randy Kobes <randy@theoryx5.uwinnipeg.ca>
For the basic interface to the cephes fraction routines, see Math::Cephes. See also Math::Fraction for a more extensive interface to fraction routines.
The C code for the Cephes Math Library is Copyright 1984, 1987, 1989, 2002 by Stephen L. Moshier, and is available at http://www.netlib.org/cephes/. Direct inquiries to 30 Frost Street, Cambridge, MA 02140.
The perl interface is copyright 2000, 2002 by Randy Kobes. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Math-Cephes documentation | Contained in the Math-Cephes distribution. |
############# Class : fract ############## package Math::Cephes::Fraction; use strict; use vars qw(%OWNER @ISA %ITERATORS @EXPORT_OK %EXPORT_TAGS $VERSION); require Exporter; *import = \&Exporter::import; #my @fract = qw(radd rsub rmul rdiv euclid fract mixed_fract); my @fract = qw(euclid fract mixed_fract); @EXPORT_OK = (@fract); %EXPORT_TAGS = ('fract' => [@fract]); $VERSION = '0.47'; #use Math::Cephes qw(new_fract euclid); require Math::Cephes; @ISA = qw( Math::Cephes ); %OWNER = (); %ITERATORS = (); *swig_n_get = *Math::Cephesc::fract_n_get; *swig_n_set = *Math::Cephesc::fract_n_set; *swig_d_get = *Math::Cephesc::fract_d_get; *swig_d_set = *Math::Cephesc::fract_d_set; sub new { my $pkg = shift; my $self = Math::Cephesc::new_fract(@_); bless $self, $pkg if defined($self); } sub DESTROY { return unless $_[0]->isa('HASH'); my $self = tied(%{$_[0]}); return unless defined $self; delete $ITERATORS{$self}; if (exists $OWNER{$self}) { Math::Cephesc::delete_fract($self); delete $OWNER{$self}; } } sub DISOWN { my $self = shift; my $ptr = tied(%$self); delete $OWNER{$ptr}; } sub ACQUIRE { my $self = shift; my $ptr = tied(%$self); $OWNER{$ptr} = 1; } sub fract { return Math::Cephes::Fraction->new(@_); } sub n { my ($self, $value) = @_; return $self->{n} unless $value; $self->{n} = $value; return $value; } sub d { my ($self, $value) = @_; return $self->{d} unless $value; $self->{d} = $value; return $value; } sub euclid { return Math::Cephes::euclid($_[0], $_[1]); } sub mixed_fract { my $f = shift; my $nin = int($f->{n}); my $din = int($f->{d}); my $gcd; if ($din < 0) { $din *= -1; $nin *= -1; } if (abs($nin) < abs($din)) { if ( $nin == 0 ) { return (0, 0, 0); } else { ($gcd, $nin, $din) = euclid($nin, $din); return (0, $nin, $din); } } else { my $n = abs($nin) % $din; my $w = int($nin / $din); if ($n == 0) { return ($w, 0, 1); } else { ($gcd, $n, $din) = euclid($n, $din); return ($w, $n, $din); } } } sub as_string { my $f = shift; my ($gcd, $string); my $num = int($f->{n}); my $den = int($f->{d}); if ( abs($num % $den) == 0) { my $w = $num / $den; $string = "$w"; } elsif ($num == 0) { $string = '0'; } else { if ($den < 0) { $num *= -1; $den *= -1; } ($gcd, $num, $den) = euclid($num, $den); $string = "$num/$den"; } return $string; } sub as_mixed_string { my $f = shift; my ($gcd, $string); my $num = int($f->{n}); my $den = int($f->{d}); if ($den < 0) { $den *= -1; $num *= -1; } if (abs($num) < abs($den)) { if ( $num == 0 ) { $string = '0'; } else { ($gcd, $num, $den) = euclid($num, $den); $string = "$num/$den"; } } else { my $n = abs($num) % $den; my $w = int($num / $den); if ($n == 0) { $string = "$w"; } else { ($gcd, $num, $den) = euclid($num, $den); $string = "$w $n/$den"; } } return $string; } sub radd { my ($f1, $f2) = @_; my $f = Math::Cephes::Fraction->new(); Math::Cephes::radd($f1, $f2, $f); return $f; } sub rsub { my ($f1, $f2) = @_; my $f = Math::Cephes::Fraction->new(); Math::Cephes::rsub($f2, $f1, $f); return $f; } sub rmul { my ($f1, $f2) = @_; my $f = Math::Cephes::Fraction->new(); Math::Cephes::rmul($f1, $f2, $f); return $f; } sub rdiv { my ($f1, $f2) = @_; my $f = Math::Cephes::Fraction->new(); Math::Cephes::rdiv($f2, $f1, $f); return $f; } 1; __END__