Para simplificar la construcción de la clase, parta del siguiente constructor (debido a Dave Cross):
1 sub new { 2 my $class = shift; 3 4 my $self; 5 if (@_ >= 2) { 6 return unless $_[0] =~ /^-?\d+$/ and $_[1] =~ /^-?\d+$/; 7 8 $self->{num} = $_[0]; 9 $self->{den} = $_[1]; 10 } elsif (@_ == 1) { 11 if (ref $_[0]) { 12 if (UNIVERSAL::isa($_[0], $class)) { 13 return $class->new($_[0]->{num}, 14 $_[0]->{den}); 15 } else { 16 croak "Can't make a $class from a ", 17 ref $_[0]; 18 } 19 } else { 20 return unless $_[0] =~ m|^(-?\d+)/(-?\d+)|; 21 22 $self->{num} = $1; 23 $self->{den} = $2; 24 } 25 } else { 26 $self->{num} = 0; 27 $self->{den} = 1; 28 } 29 bless $self, $class; 30 31 $self->normalise; 32 33 return $self; 34 }Explique las múltiples funcionalidades del constructor. A continuación sigue el código de
normalise
:
sub normalise { my $self = shift; my $hcf = _hcf($self->{num}, $self->{den}); for (qw/num den/) { $self->{$_} /= $hcf; } if ($self->{den} < 0) { for (qw/num den/) { $self->{$_} *= -1; } } }la subrutina
normalise
llama a _hcf
(del inglés
highest common factor o en español máximo común divisor)
para permitir la reducción de la fracción:
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; }