Hi all,

This is the numeric literals part, reformated to follow Michael's 
outline.

It has some additions:

 - Complex numbers
 - Further explanation of NaN/Inf, with a tentative algebra table.
 - Caveats when using BigInts/BigRats  

There are some open questions, but I think I am finally not forgetting 
any kind of numbers.

I am specially interested in the BigInt/BigRats part. It documents the 
current behaviour (in perl5, using Math::BigInt), but maybe Perl6 
will do better.

-angel

-----------------------------------------
=section * Numeric Literals

=section ** Integer and Decimal literals

There are many ways to specify literal numeric values in
perl, but they default to base 10 for input and output.

 print 14; 
 print -123.5;

=section ** Scientific (or exponential) notation

Perl allows you to use the standard scientific notation
to represent floating-point literals. For example:

 my $x = 7.823e6;

This notation is designed to let you write very large or
very small numbers efficiently.

It works just like the standard scientific notation:
the left portion of the C<e> is the coefficient, and the
right is the exponent, so a number of the form C<C.CCCeEE>
is actually intepreted as C<C.CCC * 10**EE>.

For example, the literal C<7.828e6> is interpreted as
C<7823000>.

You can use negative numbers in the exponent side, allowing
you to write very small numbers.

 my $x = 0.00000000000345; 
 my $x = 3.45e-12;            # equivalent

=section ** Radix Notation

For integer numbers, you can represent the literal value
in any other base, using the C<radix:dddddddd> syntax.

For example:

 my $i = 2:101110;                # binary 
 my $j = 3:1210112;               # tertiary 
 my $k = 8:1270;                  # octal

Printing these would give 46, 1310, and 696
respectively. When the base is greater than 10, there is
a need to represent digits that are greater than 9.

You can do this in two ways:

=over

=item *

Alphabetic characters: Following the standard convention,
perl will interpret the A letter as the digit 10, the B
letter as digit 11, and so on.

 my $l = 16:1E3A7;                 # hexadecimal

=item *

Separating by dots: You can also write each digit in its
decimal representation, and separate digits using the C<.>
character.

 my $m = 256:255.255.255.0;        # 256-base

=back

For example, the integer 30 can be written in hexadecimal
base in two equivalent ways:

  my $x = 16:1D;
  my $x = 16:1.14;

These two representations are incompatible, so writing
something like C<16:D.13> will generate a compile-time
error.

Also note that a compile-time error will be generated
if you specify a "digit" that is larger than your radix
can support.  For instance,

 my $x = 3:23; # error

Beware that when writing negative integers, the negative
character C<-> should be at the leftest point of the
expression:

 my $z = -256:234.254;                  # negative number
 my $e = 256:-234.254;                  # error

Keep in mind that once the number has been read by perl
it becomes just a magnitude. That is it loses all trace of
the way it was originally represented and is just a number. 
Perl will use decimal base when printing all the numbers, no 
matter what base did you use to type them.

=section ** Underscore character as a seprator

Perl allows the underscore character, C<_>, to be placed as
a separator between the digits of any literal number. You
can use this to break up long numbers into more readable
forms.

There aren't any rules to it; you can use it however
you like:

 123_456_000.000   (floating point)
 2:0110_1000       (binary) 
 16:FF_88_EE       (hexidecimal) 
 1312512.25        (decimal number) 
 1_312_512.25      (the same)

You can only insert the C<_> character beween two digits,
so this will generate a compile-time error:

 _2_3_4____5___6   (error)

=section ** Complex Numbers

Any integer of decimal number, followed by the C<i> letter
will be interpreted as an imaginary number. For example:

 print 2i*3i;    # prints -6

This lets you easily create complex numbers:

 my $z = 2.3 + 1i;

The C<1i> and C<-1i> numbers can be also written
respectively, C<i> and C<-i>, so the previous example
could be rewritten:

 my $z = 2.3 + i;

=section ** Pseudo-Numbers

=section *** NaN

The value C<NaN> ("Not a Number") may be returned by some
functions or operations to signal that the result of a
calculation (for example, division by zero) cannot be
represented by a numeric value.

In operations between C<NaN> and other numbers, the result
is always C<NaN> again.

 print 0 * NaN;    # NaN 
 print Nan / NaN;  # NaN

Moreover, C<NaN> is special in that it is never numerically
equal to any number, so even the expression C<NaN == NaN>
is false.

NOTE: what about C<NaN != NaN>, is it true or false?

=section *** Inf

The terms C<Inf> and C<-Inf> represent positive and
negative infinity; you may sometimes use these to create
infinite lists.

For the C<Inf> values, perl will operate them following
the standard conventions. For example:

 Operation     Result
 ----------    ------
  Inf + $X      Inf
  Inf + Inf     Inf

  Inf - $X      Inf
  Inf - Inf     NaN

  Inf * $P      Inf
  Inf * $N      Inf 
  Inf * 0       NaN
  Inf * Inf     Inf

  Inf / $P      Inf 
  Inf / $N     -Inf 
  Inf / 0       NaN (or Inf?, but then which sign?)
  Inf / Inf     NaN

  $P ** Inf     Inf 
  $N ** Inf     NaN 
  0  ** Inf     0

Here C<$P> and C<$N> represent respectively any positive
and negative values, and C<$X> represents any finite number
without restrictions (including complex numbers).

NOTE: This table is not complete, but completing it would
make it horrible lengthy. Is it really worth?

=section * Caveats when using BigNum/BigRats

All literal numbers are interepreted at compile-time,
before there is any information available about the type
of the variable that will store them.

This can produce undesired effects when working with
customs types of numbers, such as BigInt (arbitrary size
integers) and BigRats (Decimal numbers with a precision
level greater than the one of native types).

For example:

 my BigInt $i = 777_666_555_444_333_222_111;
 print $i;  # prints 77766655544433300000

This happens because the C<777_666_555_444_333_222_111>
literal is interpreted as an untyped number, and since
it is too big to be stored in the native integer type,
is automatically promoted to the floating point number
C<7.77666555444333e+20>. When this is number is stored as
a BigInt number it has alreadly lost the last digits.

If you need to create BigInt numbers without risking to
lose precision, you should write them as a string literals:

 my BigInt $i = '777_666_555_444_333_222_111'; 
 print $i; # prints 777666555444333222111

In that case the conversion to a number type happens
at run-time, and is controlled by the type of C<$i>,
so everything goes well.

=seealso String Literals 
=seealso Typing Variables 
=seealso BigInt/BigRats reference


Reply via email to