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



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