Skip to content

Commit

Permalink
[CaR Grant] Document division by zero and zero-denominator rationals
Browse files Browse the repository at this point in the history
  • Loading branch information
zoffixznet committed May 9, 2018
1 parent 1f61fd4 commit 5bc6ac8
Showing 1 changed file with 68 additions and 0 deletions.
68 changes: 68 additions & 0 deletions doc/Language/numerics.pod6
Expand Up @@ -286,6 +286,74 @@ say ⅓.perl; # OUTPUT: «<1/3>␤»
say <4/2>.nude; # OUTPUT: «(2 1)␤»
=end code
=head1 Division By Zero
In many languages division by zero is an immediate exception. In Perl 6, what
happens depends on what you're dividing and how you use the result.
Perl 6 follows L<IEEE 754-2008 Standard for Floating-Point Arithmetic|https://en.wikipedia.org/wiki/IEEE_754>, but for historical reasons
6.c language does not comply fully. L<Num> division by zero produces a
L<Failure>, while L<Complex> division by zero produces C<NaN> components,
regardlesss of what the numerator is.
As of 6.d language, both L<Num> and L<Complex> division by zero will produce
a L<-Inf>, L<+Inf>, or L<NaN> depending on whether the numerator was negative, positive, or zero, respectively (for L<Complex> the real and imaginary
components are L<Num> and are considered separately).
Division of L<Int> numerics produces a L<Rat> object (or a L<Num>, if
after reduction the denominator is larger than 64-bits, which isn't the case
when you're dividing by zero). This means such division never produces neither
an L<Exception> nor a L<Failure>. The result is a Zero-Denominator Rational,
which can be explosive.
=head2 Zero-Denominator Rationals
A Zero-Denominator Rational is a numeric that does role L<Rational>, which
among core numerics would be L<Rat>, L<MidRat>, and L<FatRat> objects, which
has denominator of zero.
On creation, the numerator of such numerics is always normalized to C<-1>,
C<1>, C<0>, depending on whether the original numerator is negative,
positive, or zero respectively:
=beging code
say <1000/0>.nude; # OUTPUT: «(1 0)␤»
say <-1000/0>.nude; # OUTPUT: «(-1 0)␤»
say <0/0>.nude; # OUTPUT: «(0 0)␤»
=end code
Operations that can be performed without requiring actual division to occur
are non-explosive. For example, you can separately examine
L<numerator> and L<denominator> in the L<nude> or perform mathematical
operations without any exceptions or failures popping up.
Converting zero-denominator rationals to L<Num> follows
the L<IEEE|https://en.wikipedia.org/wiki/IEEE_754> conventions, and the
result is a C<-Inf>, C<Inf>, or C<NaN>, depending on whether the numerator
is negative, positive, or zero, respectively. The same is true going the
other way: converting C<±Inf>/C<NaN> to one of the L<Rational> types will
produce a zero-denominator rational with an appropriate numerator:
=begin code
say <1/0>.Num; # OUTPUT: «Inf␤»
say <-1/0>.Num; # OUTPUT: «-Inf␤»
say <0/0>.Num; # OUTPUT: «NaN␤»
say Inf.Rat.nude; # OUTPUT: «(1 0)␤»
=end code
All other operations that require
non-L<IEEE|https://en.wikipedia.org/wiki/IEEE_754> division of the numerator
and denominator to occur will result in C<X::Numeric::DivideByZero> exception
to be thrown. The most common of such operations would likely be trying to
print or stringify a zero-denominator rational:
=begin code
say 0/0;
# OUTPUT:
# Attempt to divide by zero using div
# in block <unit> at -e line 1
=end code
=head1 Allomorphs
L<Allomorphs|/language/glossary#index-entry-Allomorph> are subclasses of two types that can
Expand Down

0 comments on commit 5bc6ac8

Please sign in to comment.