Fraction example
{
package MooseX::Number::Fraction;
use Moose;
use overload
q("") => 'to_string',
'0+' => 'to_num',
'+' => 'add',
fallback => 1;
has num => ( is => 'rw', isa => 'Int' );
has den => ( is => 'rw', isa => 'Int' );
sub BUILD {
my ($self) = @_;
$self->_normalise;
}
sub to_string {
my ($self) = @_;
if ( $self->den eq 1 ) {
return $self->num;
}
else {
return sprintf "%s/%s", $self->num, $self->den;
}
}
sub _normalise {
my ($self) = @_;
my $hcf = _hcf( $self->num, $self->den );
for (qw/num den/) {
$self->$_( $self->$_ / $hcf );
}
if ( $self->{den} < 0 ) {
for (qw/num den/) {
$self->$_( $self->$_ * -1 );
}
}
}
sub to_num {
my ($self) = @_;
return $self->num / $self->den;
}
sub _hcf {
my ( $x, $y ) = @_;
( $x, $y ) = ( $y, $x ) if $y > $x;
return $x if $x == $y;
while ($y) {
( $x, $y ) = ( $y, $x % $y );
}
return $x;
}
sub add {
my ( $l, $r, $rev ) = @_;
if ( ( ref $r ) eq 'MooseX::Number::Fraction' ) {
return ( ref $l )->new( num => ( $l->num * $r->den + $r->num * $l->den ), den => ( $r->den * $l->den ) );
}
else {
if ( $r =~ /^[-+]?\d+$/ ) {
return $l + ( ref $l )->new( num => $r, den => 1 );
}
else {
return $l->to_num + $r;
}
}
}
no Moose;
}
my $half = MooseX::Number::Fraction->new( num => 1, den => 2 );
my $quarter = MooseX::Number::Fraction->new( num => 1, den => 4 );
my $three_forths = MooseX::Number::Fraction->new( num => 3, den => 4 );
my $result = $half + $quarter + $three_forths;
$result += 2;
printf "%s \n%f", $result, $result;
7/2
3.500000