Author: lwall
Date: 2009-11-27 18:16:22 +0100 (Fri, 27 Nov 2009)
New Revision: 29203

Modified:
   docs/Perl6/Spec/S02-bits.pod
   docs/Perl6/Spec/S32-setting-library/Numeric.pod
Log:
[S02] clarify when precision may (not) be lost on Rat calculation
[S32/Numeric] add scaling option to round()


Modified: docs/Perl6/Spec/S02-bits.pod
===================================================================
--- docs/Perl6/Spec/S02-bits.pod        2009-11-27 15:38:38 UTC (rev 29202)
+++ docs/Perl6/Spec/S02-bits.pod        2009-11-27 17:16:22 UTC (rev 29203)
@@ -677,20 +677,41 @@
 However, for pragmatic reasons, C<Rat> values are guaranteed to be
 exact only up to a certain point.  By default, this is the precision
 that would be represented by the C<Rat64> type, which is an alias for
-C<Rational[Int,int64]>, which has a numerator
-of C<Int> but is limited to a denominator of C<int64>.  A C<Rat64> that
+C<Rational[Int,uint64]>, which has a numerator
+of C<Int> but is limited to a denominator of C<uint64>.  A C<Rat64> that
 would require more than 64 bits of storage in the denominator is
 automatically converted either to a C<Num> or to a lesser-precision
 C<Rat>, at the discretion of the implementation.  (Native types such
 as C<rat64> 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 C<rat8> actually supports C<Rational[int16,int8], allowing
+a C<rat8> actually supports C<Rational[int16,uint8], allowing
 numbers like C<100.01> to be represented, and a C<rat64>,
 defined as C<Rational[int128,int64]>, can hold the number of seconds since
 the Big Bang with attosecond precision.  Though perhaps not with
 attosecond accuracy...)
 
+The limitation on C<Rat> values is intended to be enforced only on
+user-visible types.  Intermediate values used internally in calculation
+the values of C<Rat> operators may exceed this precision, or represent
+negative denominators.  That is, the temporaries used in calculating
+the new numerator and denominator are (at least in the abstract) of
+C<Int> type.  After a new numerator and denominator are determined,
+any sign is forced to be represented only by the numerator.  Then if
+the denominator exceeds the storage size of the unsigned integer used,
+the fraction is reduced via gcd.  If the resulting denominator is still
+larger than the storage size, then and I<only> then may the precision
+be reduced to fit into a C<Rat> or C<Num>.
+
+C<Rat> addition and subtraction should attempt to preserve the
+denominator of the more precise argument if that denominator is
+an integral multiple of the less precise denominator.  That is,
+in practical terms, adding a column of dollars and cents should
+generally end up with a result that has a denominator of 100, even
+if values like 42 and 3.5 were added in.  With other operators,
+this guarantee cannot be made; in such cases, the user should probably
+be explicitly rounding to a particular denominator anyway.
+
 For applications that really need arbitrary precision denominators as
 well as numerators at the cost of performance, C<FatRat> may be used,
 which is defined as C<Rational[Int,Int], that is, as arbitrary precision in

Modified: docs/Perl6/Spec/S32-setting-library/Numeric.pod
===================================================================
--- docs/Perl6/Spec/S32-setting-library/Numeric.pod     2009-11-27 15:38:38 UTC 
(rev 29202)
+++ docs/Perl6/Spec/S32-setting-library/Numeric.pod     2009-11-27 17:16:22 UTC 
(rev 29203)
@@ -19,8 +19,8 @@
 
     Created: 19 Mar 2009 extracted from S29-functions.pod
 
-    Last Modified: 1 Sep 2009
-    Version: 3
+    Last Modified: 27 Nov 2009
+    Version: 4
 
 The document is a draft.
 
@@ -182,11 +182,19 @@
 
 =item round
 
- our Int multi method round ( Real $x: ) is export
+ our Int multi method round ( Real $x: $scale = 1) is export
 
-Returns the nearest integer to C<$x>.  The algorithm is C<floor($x + 0.5)>.
+Returns the nearest integer to C<$x>.  The algorithm is:
+
+    floor($x / $scale + 0.5) * $scale
+
 (Other rounding algorithms will be given extended names beginning with 
"round".)
 
+Functions that round to a particular precision may easily be created with
+currying:
+
+    constant &roundcents ::= &round.assuming(:scale(1/100));
+
 =item truncate
 
  our Int multi method truncate ( Real $x: ) is export

Reply via email to