Re: r29121 - docs/Perl6/Spec

2009-11-18 Thread Ron
 +Although most rational implementations normalize or reduce fractions
 +to their smallest representation immediately through a gcd algorithm,
 +Perl allows a rational datatype to do so lazily at need, such as
 +whenever the denominator would run out of precision, but avoid the
 +overhead otherwise.  Hence, if you are adding a bunch of CRats that
 +represent, say, dollars and cents, the denominator may stay 100 the
 +entire way through.  The C.nu and C.de methods will return these
 +unreduced values.  You can use C$rat.=norm to normalize the fraction.
 +The C.perl method will produce a decimal number if the denominator is
 +a multiple of 10.  Otherwise it will normalize and return a rational
 +literal of the form -47/3.  Stringifying a rational always converts
 +to CNum and stringifies that, so the rational internal form is
 +somewhat hidden from the casual user, who would generally prefer
 +to see decimal notation.

Wouldn't it be better to produce a decimal number if the denominator
equals of 2**n * 5**m for n,m unsigned int? Before displaying the
value should be decimal-normalized by multiplying numerator and
denominator by 2**|n-m| or 5**|n-m| depending on sign(n-m).
Otherwise adding Rats representing dollars and cents which are
immediately normalized could produce flapping between rational literal
form and decimal number form.
Aside from that the specification should be: if the denominator equals
10**n, with n unsigned integer, .perl will produce a decimal number.
Otherwise 1/30 would produce a decimal number like 0.033..., which
was probably not intended.

Regards,
Ron



Rat.perl (was: [pugs-commits] r29121 - docs/Perl6/Spec)

2009-11-18 Thread Moritz Lenz
pugs-comm...@feather.perl6.nl wrote:
 +The C.perl method will produce a decimal number if the denominator is
 +a multiple of 10.  Otherwise it will normalize and return a rational
 +literal of the form -47/3.

Did you mean a power of 10 instead? I can't see how it makes sense
right now.

This would be the .perl representation by current spec:

08:46 @moritz_ rakudo: say 357/12540
08:46 +p6eval rakudo 7347ec: 0.0284688995215311␤

instead of

08:44 @moritz_ rakudo: say (357/12540).perl
08:44 +p6eval rakudo 7347ec: 119/4180␤

At least I don't see the point of special-casing one trailing zero in
the denominator.

Cheers,
Moritz

-- 
Moritz Lenz
http://perlgeek.de/ |  http://perl-6.de/ | http://sudokugarden.de/


Re: r29121 - docs/Perl6/Spec

2009-11-18 Thread Larry Wall
On Wed, Nov 18, 2009 at 03:08:59AM -0800, Ron wrote:
:  +Although most rational implementations normalize or reduce fractions
:  +to their smallest representation immediately through a gcd algorithm,
:  +Perl allows a rational datatype to do so lazily at need, such as
:  +whenever the denominator would run out of precision, but avoid the
:  +overhead otherwise.  Hence, if you are adding a bunch of CRats that
:  +represent, say, dollars and cents, the denominator may stay 100 the
:  +entire way through.  The C.nu and C.de methods will return these
:  +unreduced values.  You can use C$rat.=norm to normalize the fraction.
:  +The C.perl method will produce a decimal number if the denominator is
:  +a multiple of 10.  Otherwise it will normalize and return a rational
:  +literal of the form -47/3.  Stringifying a rational always converts
:  +to CNum and stringifies that, so the rational internal form is
:  +somewhat hidden from the casual user, who would generally prefer
:  +to see decimal notation.
: 
: Wouldn't it be better to produce a decimal number if the denominator
: equals of 2**n * 5**m for n,m unsigned int? Before displaying the
: value should be decimal-normalized by multiplying numerator and
: denominator by 2**|n-m| or 5**|n-m| depending on sign(n-m).
: Otherwise adding Rats representing dollars and cents which are
: immediately normalized could produce flapping between rational literal
: form and decimal number form.
: Aside from that the specification should be: if the denominator equals
: 10**n, with n unsigned integer, .perl will produce a decimal number.
: Otherwise 1/30 would produce a decimal number like 0.033..., which
: was probably not intended.

Good catch; I thought power and typed multiple.

I was hesitating to extend it to require factoring for the solution,
but there's actually a fast way to factor for 2's and 5's.  Just shift
off all the 0 bits on the bottom to take out all the 2's, and then
look up the remaining number to see if it's a power of 5.

So I'm inclined to make normal stringification also produce an exact decimal
by default and only failover to Num if .perl would produce the 1/3 form.
In the absence of an explicit format, I think exactness should trump
limiting the size of the resulting string arbitrarily.

Larry


r29121 - docs/Perl6/Spec

2009-11-17 Thread pugs-commits
Author: lwall
Date: 2009-11-18 01:53:40 +0100 (Wed, 18 Nov 2009)
New Revision: 29121

Modified:
   docs/Perl6/Spec/S02-bits.pod
   docs/Perl6/Spec/S09-data.pod
Log:
[S02,S09] more tweakage of rat semantics
Rat types are instantiations of a Rational role as suggested by moritz_++


Modified: docs/Perl6/Spec/S02-bits.pod
===
--- docs/Perl6/Spec/S02-bits.pod2009-11-17 23:59:27 UTC (rev 29120)
+++ docs/Perl6/Spec/S02-bits.pod2009-11-18 00:53:40 UTC (rev 29121)
@@ -629,12 +629,15 @@
 are generally not used directly as object types.  For instance
 all the numeric types perform the CNumeric role, and all
 string types perform the CStringy role, but there's no
-such thing as a Numeric object.  Common roles include:
+such thing as a Numeric object, since these are generic
+types that must be instantiated with extra arguments to produce
+normal object types.  Common roles include:
 
 Stringy
 Numeric
 Real
 Integral
+Rational
 Callable
 Positional
 Associative
@@ -654,7 +657,7 @@
 but by default it is the same type as a native Cnum.  See below.
 
 CRat supports extended precision rational arithmetic.
-Dividing two CInt objects using C infix:/  produces a
+Dividing two CIntegral objects using C infix:/  produces a
 a CRat, which is generally usable anywhere a CNum is usable, but
 may also be explicitly cast to CNum.  (Also, if either side is
 CNum already, C infix:/  gives you a CNum instead of a CRat.)
@@ -673,7 +676,8 @@
 
 However, for pragmatic reasons, CRat values are guaranteed to be
 exact only up to a certain point.  By default, this is the precision
-that would be represented by the CRat64 type, which has a numerator
+that would be represented by the CRat64 type, which is an alias for
+CRational[Int,int64], which has a numerator
 of CInt but is limited to a denominator of Cint64.  A CRat64 that
 would require more than 64 bits of storage in the denominator is
 automatically converted either to a CNum or to a lesser-precision
@@ -681,21 +685,36 @@
 as Crat64 limit the size of both numerator and denominator, though
 not to the same size.  The numerator should in general be twice the
 size of the denominator to support user expectations.  For instance,
-a Crat8 should actually support Cint16/int8, allowing
+a Crat8 actually supports CRational[int16,int8], allowing
 numbers like C100.01 to be represented, and a Crat64,
-defined as Cint128/int64, can hold the number of seconds since
-the Big Bang with picosecond precision.  Though perhaps not with
-picosecond accuracy...)
+defined as CRational[int128,int64], can hold the number of seconds since
+the Big Bang with attosecond precision.  Though perhaps not with
+attosecond accuracy...)
 
 For applications that really need arbitrary precision denominators as
-well as numerators at the cost of performance, CRatio may be used,
-which is stored as CInt/Int, that is, as arbitrary precision in
-both parts.  There is no literal form for a CRatio, so it must
-be constructed using CRatio.new($nu,$de).  In general, only math
-operators with at least one CRatio argument will return another
-CRatio, to prevent accidental promotion of reasonably fast CRat
-values into arbitrarily slow CRatio values.
+well as numerators at the cost of performance, CFatRat may be used,
+which is defined as CRational[Int,Int], that is, as arbitrary precision in
+both parts.  There is no literal form for a CFatRat, so it must
+be constructed using CFatRat.new($nu,$de).  In general, only math
+operators with at least one CFatRat argument will return another
+CFatRat, to prevent accidental promotion of reasonably fast CRat
+values into arbitrarily slow CFatRat values.
 
+Although most rational implementations normalize or reduce fractions
+to their smallest representation immediately through a gcd algorithm,
+Perl allows a rational datatype to do so lazily at need, such as
+whenever the denominator would run out of precision, but avoid the
+overhead otherwise.  Hence, if you are adding a bunch of CRats that
+represent, say, dollars and cents, the denominator may stay 100 the
+entire way through.  The C.nu and C.de methods will return these
+unreduced values.  You can use C$rat.=norm to normalize the fraction.
+The C.perl method will produce a decimal number if the denominator is
+a multiple of 10.  Otherwise it will normalize and return a rational
+literal of the form -47/3.  Stringifying a rational always converts
+to CNum and stringifies that, so the rational internal form is
+somewhat hidden from the casual user, who would generally prefer
+to see decimal notation.
+
 =item *
 
 Perl 6 should by default make standard IEEE floating point concepts
@@ -1091,7 +1110,7 @@
 Int Perl integer (allows Inf/NaN, arbitrary precision, etc.)
 Num Perl number (approximate Real, generally via floating point)
 Rat Perl rational (exact Real, limited denominator)
-