Permalink
Fetching contributors…
Cannot retrieve contributors at this time
141 lines (84 sloc) 4.08 KB
=begin pod
=TITLE role Rational
=SUBTITLE Number stored as numerator and denominator
role Rational[::NuT, ::DeT] does Real { ... }
C<Rational> is the common role for numbers that are stored as pairs of
numerator and denominator. It is parameterized by the types of the numerator (C<NuT>)
and denominator (C<DeT>). By default, these are C<Int>, but other types of C<Rational> are possible by using a different parameterization
class Positive does Rational[UInt] {};
my Positive $one-third = Positive.new(1,3);
say $one-third; # OUTPUT: «0.333333␤»
my Positive $fail =Positive.new(-2,3); # OUTPUT: «Type check failed in binding to parameter 'nu'; expected UInt but got Int (-2)␤»
Please note that, since C<DeT> is by default equal to C<NuT>, in this case both are instantiated to C<UInt>. Built into Perl 6 are L<Rat> and L<FatRat>, which both do the C<Rational> role.
=head1 Methods
=head2 method new
=for code :skip-test
method new(NuT:D: $numerator, DeT:D: $denominator --> Rational:D)
Creates a new rational object from numerator and denominator, which it
normalizes to the lowest terms. The C<$denominator> can be zero, in which
case the numerator is normalized to C<-1>, C<0>, or C<1> depending on whether
the original is negative, zero, or positive, respectively.
=head2 method Bool
Defined as:
multi method Bool(Rational:D: --> Bool:D)
Returns C<False> if L<numerator> is C<0>, otherwise returns C<True>. This applies for
C«<0/0>» zero-denominator L<Rational> as well, despite C«?<0/0>.Num» being C<True>.
=head2 method Int
Defined as:
method Int(Rational:D: --> Int:D)
Coerces the invocant to L<Int> by truncating non-whole portion of the represented
number, if any. If the L<denominator> is zero, will L<fail> with
C<X::Numeric::DivideByZero>.
=head2 method Num
Defined as:
method Num(Rational:D: --> Num:D)
Coerces the invocant to L<Num> by dividing L<numerator> by L<denominator>.
If L<denominator> is C<0>, returns C<Inf>, C<-Inf>, or C<NaN>, based on
whether L<numerator> is a positive number, negative number, or C<0>,
respectively.
=head2 method ceiling
Defined as:
method ceiling(Rational:D: --> Int:D)
Return the smallest integer not greater than the invocant. If L<denominator>
is zero, L<fails|/routine/fail> with C<X::Numeric::DivideByZero>.
=head2 method floor
Defined as:
method floor(Rational:D: --> Int:D)
Return the largest integer not greater than the invocant. If L<denominator>
is zero, L<fails|/routine/fail> with C<X::Numeric::DivideByZero>.
=head2 method isNaN
=for code
method isNaN(Rational:D: --> Bool:D)
Tests whether the invocant's Num value is a NaN. That is both its numerator
and denominator are zero.
=head2 method numerator
=for code :skip-test
method numerator(Rational:D: --> NuT:D)
Returns the numerator.
=head2 method denominator
=for code :skip-test
method denominator(Rational:D: --> DeT:D)
Returns the denominator.
=head2 method nude
method nude(Rational:D: --> Positional)
Returns a list of the numerator and denominator.
=head2 method norm
method norm(Rational:D: --> Rational:D)
Returns a normalized Rational object, i.e. with positive denominator, and
numerator and denominator coprime.
=head2 method base-repeating
method base-repeating(Rational:D: Int:D() $base = 10)
Returns a list of two strings that, when concatenated, represent the number in
base C<$base>. The second element is the one that repeats. For example:
my ($non-rep, $repeating) = (19/3).base-repeating(10);
say $non-rep; # OUTPUT: «6.␤»
say $repeating; # OUTPUT: «3␤»
printf '%s(%s)', $non-rep, $repeating; # OUTPUT: «6.(3)»
19/3 is 6.333333... with the 3 repeating indefinitely.
If no repetition occurs, the second string is empty:
say (5/2).base-repeating(10).perl; # OUTPUT: «("2.5", "")␤»
The precision for determining the repeating group is limited to 1000
characters, above that, the second string is C<???>.
C<$base> defaults to C<10>.
=end pod
# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6