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