Version 0.1, March 06, 2017
This package provides a Pure port of Q+Q, Rob Hubbard’s rational number library for the Q programming language. The port was done by Jiri Spitz. It contains rational.pure
, a collection of utility functions for rational numbers, and rat_interval.pure
, a module for doing interval arithmetic needed by rational.pure
. These modules are designed to work with the math.pure
module (part of the standard Pure library), which contains the definition of Pure’s rational type and implements the basic rational arithmetic.
This document is an edited version of Rob’s original Q+Q manual available from the Q website, slightly adjusted to account for the Pure specifics of the implementation. In particular, note that the operations provided by rational.pure
and rat_interval.pure
live in their own rational
and interval
namespaces, respectively, so if you want to get unqualified access to the symbols of these modules (as the examples in this manual assume) then you’ll have to import the modules as follows:
using rational, rat_interval;
using namespace rational, interval;
Also note that rational always pulls in the math module, so you don’t have to import the latter explicitly if you are using rational.
Another minor difference to the Q version of this module is that rational results always have Pure bigints as their numerators and denominators, hence the L
suffix in the printed results. Also, unary minus binds weaker in Pure than the rational division operator, so a negative rational number will be printed as, e.g., (-1L)%2L
, which looks a bit funny but is correct since Pure rationals always carry their sign in the numerator.
Pure-rational is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Pure-rational is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
Get the latest source from https://bitbucket.org/purelang/pure-lang/downloads/pure-rational-0.1.tar.gz.
Then run make install
(as root) to install pure-rational in the Pure library directory. This requires GNU make, and of course you need to have Pure installed.
make install
tries to guess your Pure installation directory. If it gets this wrong, you can install using make install prefix=/usr
which sets the installation prefix. Please see the Makefile for details.
This module provides additional operations on the rational number type provided by the math.pure
module in the standard library. The module is compatible with Pure version 0.43 (onwards).
The implementation of the rational type and associated utilities is distributed across various files.
The file math.pure
defines the type, its constructors and ‘deconstructors’ and basic arithmetical and mathematical operators and functions. This is part of the standard Pure library. A few definitions associated with rationals are also defined in other standard library modules. In particular, the type tests are contained in primitives.pure
.
It is also possible to create rational complex numbers (in addition to double complex numbers and integral or Gaussian complex numbers). That is, rationals play nicely with the complex number constructors provided in the math.pure
module. This is discussed further in Rational Complex Numbers.
Additional ‘rational utilities’, not included in the math.pure
module, are defined in rational.pure
. The functions include further arithmetical and mathematical operators and functions, continued fraction support, approximation routines and string formatting and evaluation.
The rational utilities include some ‘rational complex number’ functions.
Amongst the rational utilities are some functions that return a rational interval. The file rat_interval.pure
is a partial implementation of interval arithmetic. Intervals are discussed further in Intervals.
Throughout this document, the parameters q, q0, q1, … usually denote rationals (∈ Q), parameters z, … usually denote integers (∈ Z), r, … usually denote real numbers (∈ R), c, … usually denote complex numbers (∈ C), n, … usually denote parameters of any numeric type, v, … usually denote parameters of any interval type, and x, … usually denote parameters of any type.
The reals are not just the doubles, but include rationals and integers. The term ‘rational’ usually refers to a rational number ∈ Q ⊃ Z, or an expression of type rational or integer.
Rationals are constructed with the %
exact division operator, and other kinds of numbers can be converted to rationals with the rational
function. These are both defined in math.pure.
n1 % n2
rational x
x
to a rational.
Example 1 Constructing a fraction:
> 44%14;
22L%7L
Example 2 Converting from an integer:
> rational 3;
3L%1L
A rational number is in simplest form if the numerator and denominator are coprime (i.e. do not have a factor in common) and the denominator is positive (and, specifically, non-zero). Sometimes the term ‘irreducible’ is used for a rational in simplest form. This is a property of the representation of the rational number and not of the number itself.
num q
den q
rational::num_den q
Example 3 Using num_den to obtain a representation in simplest form:
> let q = (44%(-14));
> num q;
-22L
> den q;
7L
> num_den q;
-22L,7L
> num_den 3;
3L,1L
> num_den (-3);
-3L,1L
Together, num
and den
are a pair of ‘decomposition’ operators, and num_den
is also a decomposition operator. There are others (see Decomposition). The integer and fraction function (see Integer and Fraction Parts) may be used in conjunction with num_den_gauss
to decompose a rational into integer, numerator and denominator parts.
The functions rationalp
and ratvalp
and other rational variants are new for rationals and the standard functions exactp
and inexactp
are extended for rationals.
A value is ‘exact’, or of an exact type, if it is of a type that is able to represent the values returned by arithmetical operations exactly; in a sense, it is ‘closed’ under arithmetical operations. Otherwise, a value is ‘inexact’. Inexact types are able to store some values only approximately.
The doubles are not an exact type. The results of some operations on some values that are stored exactly, can’t be stored exactly. (Furthermore, doubles are intended to represent real numbers; no irrational number (∈ R \ Q) can be stored exactly as a double; even some rational (∈ Q) numbers are not stored exactly.)
The rationals are an exact type. All rational numbers (subject to available resources, of course) are stored exactly. The results of the arithmetical operations on rationals are rationals represented exactly. Beware that the standard intvalp
and ratvalp
may return 1 even if the value is of double type. However, these functions may be combined with exactp
.
exactp x
inexactp x
rationalp x
ratvalp x
Example 4 Rational value tests:
> let l = [9, 9%1, 9%2, 4.5, sqrt 2, 1+i, inf, nan];
> map exactp l;
[1,1,1,0,0,1,0,0]
> map inexactp l;
[0,0,0,1,1,0,1,1]
> map rationalp l;
[0,1,1,0,0,0,0,0]
> map ratvalp l;
[1,1,1,1,1,0,0,0]
> map (\x -> (exactp x && ratvalp x)) l; // "has exact rational value"
[1,1,1,0,0,0,0,0]
> map intvalp l; // for comparison
[1,1,0,0,0,0,0,0]
> map (\x -> (exactp x && intvalp x)) l; // "has exact integer value"
[1,1,0,0,0,0,0,0]
See Rational Complex Numbers for details about rational complex numbers, and Rational Complex Type and Value Tests for details of their type and value tests.
The standard arithmetic operators (+), (−) and (*) are overloaded to have at least one rational operand. If both operands are rational then the result is rational. If one operand is integer, then the result is rational. If one operand is double, then the result is double.
The operators (/) and (%) are overloaded for division on at least one rational operand. The value returned by (/) is always inexact
(in the sense of Type and Value Tests). The value returned by (%) is exact
(if it exists).
The standard function pow
is overloaded to have a rational left operand. If pow
is passed integer operands where the right operand is negative, then a rational is returned. The right operand should be an integer; negative values are permitted (because q−z = 1/qz). It is not overloaded to also have a rational right operand because such values are not generally rational (e.g. q1/n = n√q).
The standard arithmetic operator (^) is also overloaded, but produces a double value (as always).
Example 5 Arithmetic:
> 5%7 + 2%3;
29L%21L
> str_mixed ans;
"1L+8L/21L"
> 1 + 2%3;
5L%3L
> ans + 1.0;
2.66666666666667
> 3%8 - 1%3;
1L%24L
> (11%10) ^ 3;
1.331
> pow (11%10) 3;
1331L%1000L
> pow 3 5;
243L
> pow 3 (-5);
1L%243L
(See the function str_mixed
.)
Beware that (/) on integers will not produce a rational result.
Example 6 Division:
> 44/14;
3.14285714285714
> 44%14;
22L%7L
> str_mixed ans;
"3L+1L/7L"
(See the function str_mixed
.)
There is a rational-aware divide operator on the numeric types:
n1 % n2
Example 7 Using % like a constructor:
> 44 % 14;
22L%7L
> 2 + 3%8; // "2 3/8"
19L%8L
> str_mixed ans;
"2L+3L/8L"
(See the function str_mixed
.)
rational::reciprocal n
Example 8 Reciprocal:
> reciprocal (22%7);
7L%22L
The following division functions are parameterised by a rounding mode roundfun
. The available rounding modes are described in Rounding to Integer.
rational::divide roundfun n d
roundfun
(see Rounding to Integer). If roundfun
= floor
then 0 ≤ r < d. If roundfun
= ceil
then −d < r ≤ 0. If roundfun
= trunc
then |r| < |d| and sgn r ∈ {0, sgn d}. If roundfun
= round
, roundfun
= round_zero_bias
or roundfun
= round_unbiased
then |r| ≤ d/2.
rational::quotient roundfun nN d
divide
roundfun n d.
rational::modulus roundfun n d
divide
roundfun n d.
q1 div q2
q1 mod q2
The standard arithmetic operators (==), (~=), (<), (<=), (>), (>=) are overloaded to have at least one rational operand. The other operand may be rational, integer or double.
Example 9 Inequality:
> 3%8 < 1%3;
0
rational::cmp n1 n2
Example 10 Compare:
> cmp (3%8) (1%3);
1
Most mathematical functions, including the elementary functions (sin, sin −1, sinh, sinh−1, cos, … , exp, ln, … ), are not closed on the set of rational numbers. That is, most mathematical functions do not yield a rational number in general when applied to a rational number. Therefore the elementary functions are not defined for rationals. To apply these functions, first apply a cast to double, or compose the function with a cast.
The standard abs
and sgn
functions are overloaded for rationals.
abs q
sgn q
Together, these functions satisfy the property ∀q • (sgn q) * (abs q) = q (i.e. ∀q • (sgn q) * |q| = q). Thus these provide a pair of ‘decomposition’ operators; there are others (see Decomposition).
The standard functions gcd
and lcm
are overloaded for rationals, and mixtures of integer and rational.
gcd n1 n2
Example 11 With two rationals:
> let a = 7%12;
> let b = 21%32;
> let f = gcd a b;
> f;
7L%96L
> a % f;
8L%1L
> b % f;
9L%1L
Example 12 With a rational and an integer:
> let f = gcd (6%5) 4;
> f;
2L%5L
> (6%5) % f;
3L%1L
> 4 % f;
10L%1L
Example 13 With integral rationals and with integers:
> gcd (rational 18) (rational 24);
6L%1L
> gcd 18 24;
6
Example 14 The behaviour with negative numbers:
> gcd (rational (-18)) (rational 24);
6L%1L
> gcd (rational 18) (rational (-24));
6L%1L
> gcd (rational (-18)) (rational (-24));
6L%1L
lcm n1 n2
Example 15 With two rationals:
> let a = 7%12;
> let bB = 21%32;
> let m = lcm a b;
> m;
21L%4L
> m % a;
9L%1L
> m % b;
8L%1L
Example 16 With a rational and an integer:
> let m = lcm (6%5) 4;
> m;
12L%1L
> m % (6%5);
10L%1L
Example 17 The behaviour with negative numbers:
> lcm (rational (-18)) (rational 24);
72L%1L
> lcm (rational 18) (rational (-24));
72L%1L
> lcm (rational (-18)) (rational (-24));
72L%1L
Together, the GCD and LCM have the following property when applied to two numbers: (gcd q1 q2) * (lcm q1 q2) = |q1 * q2|.
The standard min
and max
functions work with rational values.
Example 18 Maximum:
> max (3%8) (1%3);
3L%8L
The ‘complexity’ (or ‘complicatedness’) of a rational is a measure of the greatness of its simplest (positive) denominator.
The complexity of a number is not itself made available, but various functions and operators are provided to allow complexities to be compared. Generally, it does not make sense to operate directly on complexity values.
The complexity functions in this section may be applied to integers (the least complex), rationals, or reals (doubles; the most complex).
Functions concerning ‘complexity’ are named with ‘cplx’, whereas functions concerning ‘complex numbers’ (see Rational Complex Numbers) are named with ‘comp’.
n1 rational::eq_cplx n2
Example 19 Complexity equality test:
> (1%3) eq_cplx (100%3);
1
> (1%4) eq_cplx (1%5);
0
> (3%3) eq_cplx (1%3); // LHS is not in simplest form
0
n1 rational::not_eq_cplx n2
n1 rational::less_cplx n2
Example 20 Complexity inequality test:
> (1%3) less_cplx (100%3);
0
> (1%4) less_cplx (1%5);
1
> (3%3) less_cplx (1%3); // LHS is not in simplest form
1
n1 rational::less_eq_cplx n2
n1 rational::more_cplx n2
n1 rational::more_eq_cplx n2
rational::cmp_complexity n1 n2
Example 21 Complexity comparison:
> cmp_complexity (1%3) (100%3);
0
> cmp_complexity (1%4) (1%5);
-1
> cmp_complexity (3%3) (1%3); // LHS is not in simplest form
-1
rational::least_cplx n1 n2
Example 22 Complexity selection:
> least_cplx (100%3) (1%3);
100L%3L
> least_cplx (1%5) (1%4);
1L%4L
> least_cplx (1%3) (3%3); // second argument not in simplest form
1L%1L
rational::most_cplx n1 n2
rational::complexity_rel n1 op n2
Example 23 Complexity relations:
> complexity_rel (1%3) (==) (100%3);
1
> complexity_rel (1%4) (<=) (1%5);
1
> complexity_rel (1%4) (>) (1%5);
0
rational::prefix_complexity_rel op n1 n2
rational::mediant q1 q2
returns the canonical mediant of the rationals q1 and q2, a form of (nonarithmetic) average on rationals. The mediant of the representations n1/d1 = q1 and n2/d2 = q2, where d1 and d2 must be positive, is defined as (n1 + n2)/(d1 + d2). A mediant of the rationals q1 and q2 is a mediant of some representation of each of q1 and q2. That is, the mediant is dependent upon the representations and therefore is not well-defined as a function on pairs of rationals. The canonical mediant always assumes the simplest representation, and therefore is well-defined as a function on pairs of rationals.
By the phrase “the mediant” (as opposed to just “a mediant”) we always mean “the canonical mediant”.
If q1 < q2, then any mediant q is always such that q1 < q < q2.
The (canonical) mediant has some special properties. If q1 and q2 are integers, then the mediant is the arithmetic mean. If q1 and q2 are unit fractions (reciprocals of integers), then the mediant is the harmonic mean. The mediant of q and 1/q is ±1, (which happens to be a geometric mean with the correct sign, although this is a somewhat uninteresting and degenerate case).
Example 24 Mediants:
> mediant (1%4) (3%10);
2L%7L
> mediant 3 7; // both integers
5L%1L
> mediant 3 8; // both integers again
11L%2L
> mediant (1%3) (1%7); // both unit fractions
1L%5L
> mediant (1%3) (1%8); // both unit fractions again
2L%11L
> mediant (-10) (-1%10);
(-1L)%1L
rational::farey k
Example 25 A Farey sequence:
> map str_mixed (farey 6);
["0L","1L/6L","1L/5L","1L/4L","1L/3L","2L/5L","1L/2L","3L/5L","2L/3L",
"3L/4L","4L/5L","5L/6L","1L"]
(See the function str_mixed
.)
Farey sequences and mediants are closely related. Three rationals q1 < q2 < q3 are consecutive members of a Farey sequence if and only if q2 is the mediant of q1 and q3. If rationals q1 = n1/d1 < q2 = n2/d2 are consecutive members of a Farey sequence, then n2d1 − n1d2 = 1.
rational::rat_simplify q
Example 26 Rational type simplification:
> let l = [9, 9%1, 9%2, 4.5, 9%1+i, 9%2+i]; l;
[9,9L%1L,9L%2L,4.5,9L%1L+:1,9L%2L+:1]
> map rat_simplify l;
[9,9,9L%2L,4.5,9+:1,9L%2L+:1]
See Rational Complex Numbers for details about rational complex numbers, and Rational Complex Type Simplification for details of their type simplification.
Some of these are new functions, and some are overloads of standard functions. The behaviour of the overloads is consistent with that of the standard functions.
floor q
ceil q
trunc q
round q
rational::round_zero_bias q
rational::round_unbiased q
Example 27 Illustration of the different rounding modes:
> let l = iterwhile (<= 3) (+(1%2)) (- rational 3);
> map double l; // (just to show the values in a familiar format)
[-3.0,-2.5,-2.0,-1.5,-1.0,-0.5,0.0,0.5,1.0,1.5,2.0,2.5,3.0]
> map floor l;
[-3L,-3L,-2L,-2L,-1L,-1L,0L,0L,1L,1L,2L,2L,3L]
> map ceil l;
[-3L,-2L,-2L,-1L,-1L,0L,0L,1L,1L,2L,2L,3L,3L]
> map trunc l;
[-3L,-2L,-2L,-1L,-1L,0L,0L,0L,1L,1L,2L,2L,3L]
> map round l;
[-3L,-3L,-2L,-2L,-1L,-1L,0L,1L,1L,2L,2L,3L,3L]
> map round_zero_bias l;
[-3L,-2L,-2L,-1L,-1L,0L,0L,0L,1L,1L,2L,2L,3L]
> map round_unbiased l;
[-3L,-2L,-2L,-2L,-1L,0L,0L,0L,1L,2L,2L,2L,3L]
(See the function double
.)
rational::integer_and_fraction roundfun q
roundfun
(see Rounding to Integer).
Example 28 Integer and fraction parts with the different rounding modes:
> let nc = -22%7;
> integer_and_fraction floor nc;
-4L,6L%7L
> integer_and_fraction trunc nc;
-3L,(-1L)%7L
> integer_and_fraction round nc;
-3L,(-1L)%7L
It is always the case that z and f have the property that q = z + f. However, the remaining properties depend upon the choice of roundfun
. Thus this provides a ‘decomposition’ operator; there are others (see Decomposition). If roundfun
= floor
then 0 ≤ f < 1. If roundfun
= ceil
then −1 < f ≤ 0. If roundfun
= trunc
then |f| < 1 and sgn f ∈ {0, sgn q}. If roundfun
= round
, roundfun
= round_zero_bias
or roundfun
= round_unbiased
then |f| ≤ 1/2.
rational::fraction roundfun q
roundfun
. The corresponding function ‘integer’ is not provided, as integer roundfun
q would be just roundfun
q. The integer and fraction function (probably with trunc
or floor
rounding mode) may be used in conjunction with num_den
(see ‘Deconstructors’) to decompose a rational into integer, numerator and denominator parts.
int q
frac q
Example 29 Standard integer and fraction parts:
> let nc = -22%7;
> int nc;
-3
> frac nc;
(-1L)%7L
rational::round_to_multiple roundfun multOf q
roundfun
as the rounding mode (see Rounding to Integer). Note that it is the multiple that is rounded in the prescribed way, and not the final result, which may make a difference in the case that multOf is negative. If that is not the desired behaviour, pass this function the absolute value of multOf rather than multOf. Similar comments apply to the following functions.
rational::floor_multiple multOf q
rational::ceil_multiple multOf q
rational::trunc_multiple multOf q
rational::round_multiple multOf q
rational::round_multiple_zero_bias multOf q
rational::round_multiple_unbiased multOf q
Example 30 Round to multiple:
> let l = [34.9, 35, 35%1, 35.0, 35.1];
> map double l; // (just to show the values in a familiar format)
[34.9,35.0,35.0,35.0,35.1]
> map (floor_multiple 10) l;
[30.0,30L,30L,30.0,30.0]
> map (ceil_multiple 10) l;
[40.0,40L,40L,40.0,40.0]
> map (trunc_multiple 10) l;
[30.0,30L,30L,30.0,30.0]
> map (round_multiple 10) l;
[30.0,40L,40L,40.0,40.0]
> map (round_multiple_zero_bias 10) l;
[30.0,30L,30L,30.0,40.0]
> map (round_multiple_unbiased 10) l;
[30.0,40L,40L,40.0,40.0]
(See the function double
.)
The round multiple functions may be used to find a fixed denominator approximation of a number. (The simplest denominator may actually be a proper factor of the chosen value.) To approximate for a bounded (rather than particular) denominator, use rational approx max den instead (see Best Approximation with Bounded Denominator).
Example 31 Finding the nearest q = n/d value to 1/e ≈ 0.368 where d = 1000 (actually, where d|1000):
> let co_E = exp (-1);
co_E;
0.367879441171442
> round_multiple (1%1000) (rational co_E);
46L%125L
> 1000 * ans;
368L%1L
Example 32 Finding the nearest q = n/d value to 1/φ ≈ 0.618 where d = 3 5 = 243 (actually, where d|243):
> let co_Phi = (sqrt 5 - 1) / 2;
> round_multiple (1%243) (rational co_Phi);
50L%81L
Other methods for obtaining a rational approximation of a number are described in R -> Q — Approximation.
double q
This section describes functions that approximate a number (usually a double) by a rational. See Rounding to Multiples for approximation of a number by a rational with a fixed denominator. See Numeral String -> Q — Approximation for approximation by a rational of a string representation of a real number.
Some of the approximation functions return an interval. The file rat_interval.pure
is a basic implementation of interval arithmetic, and is not included in the default prelude. It is not intended to provide a complete implementation of interval arithmetic. The notions of ‘open’ and ‘closed’ intervals are not distinguished. Infinite and half-infinite intervals are not specifically provided. Some operations and functions may be missing. The most likely functions to be used are simply the ‘deconstructors’; see Interval Constructors and ‘Deconstructors’.
Intervals are constructed with the function interval.
interval::interval (n1, n2)
lo_up
.
Example 33 Constructing an interval:
> let v = interval (3, 8);
> v;
interval::Ivl 3 8
interval::lower v
interval::upper v
interval::lo_up v
Example 34 Deconstructing an interval:
> lower v;
3
> upper v;
8
> lo_up v;
3,8
exactp v
inexactp v
interval::intervalp x
interval::interval_valp x
interval::ratinterval_valp x
interval::intinterval_valp x
Example 35 Interval value tests:
> let l = [interval(0,1), interval(0,1%1), interval(0,3%2), interval(0,1.5)];
> map exactp l;
[1,1,1,0]
> map inexactp l;
[0,0,0,1]
> map intervalp l;
[1,1,1,1]
> map interval_valp l;
[1,1,1,1]
> map ratinterval_valp l;
[1,1,1,1]
> map intinterval_valp l;
[1,1,0,0]
The standard arithmetic operators (+), (−), (*), (/) and (%) are overloaded for intervals. The divide operators (/) and (%) do not produce a result if the right operand is an interval containing 0.
Example 36 Some intervals:
> let a = interval (11, 19);
> let b = interval (16, 24);
> let c = interval (21, 29);
> let d = interval (23, 27);
Example 37 Interval arithmetic:
> let p = interval (0, 1);
> let s = interval (-1, 1);
> a + b;
interval::Ivl 27 43
> a - b;
interval::Ivl (-13) 3
> a * b;
interval::Ivl 176 456
> p * 2;
interval::Ivl 0 2
> (-2) * p;
interval::Ivl (-2) 0
> -c;
interval::Ivl (-29) (-21)
> s * a;
interval::Ivl (-19) 19
> a % 2;
interval::Ivl (11L%2L) (19L%2L)
> a / 2;
interval::Ivl 5.5 9.5
> reciprocal a;
interval::Ivl (1L%19L) (1L%11L)
> 2 % a;
interval::Ivl (2L%19L) (2L%11L)
> a % b;
interval::Ivl (11L%24L) (19L%16L)
> a % a; // notice that the intervals are mutually independent here
interval::Ivl (11L%19L) (19L%11L)
There are also some relations defined for intervals. The standard relations (==) and (~=) are overloaded.
However, rather than overloading (<), (<=), (>), (>=), which could be used for either ordering or containment with some ambiguity, the module defines (before)
, (within)
, and so on. ‘Strictness’ refers to the properties at the end-points.
v1 interval::before v2
v1 interval::strictly_before v2
v1 interval::after v2
v1 interval::strictly_after v2
v1 interval::within v2
v1 interval::strictly_within v2
v1 interval::without v2
v1 interval::strictly_without v2
v1 interval::disjoint v2
v interval::strictly_disjoint v2
Example 38 Interval relations:
> a == b;
0
> a == a;
1
> a before b;
0
> a before c;
1
> c before a;
0
> a disjoint b;
0
> c disjoint a;
1
> a within b;
0
> a within c;
0
> d within c;
1
> c within d;
0
> a strictly_within a;
0
> a within a;
1
(The symbols a through d were defined in Example 36.)
These may also be used with a simple (real) value, and in particular to test membership.
Example 39 Membership:
> 10 within a;
0
> 11 within a;
1
> 11.0 within a;
1
> 12 within a;
1
> 12.0 within a;
1
> 10 strictly_within a;
0
> 11 strictly_within a;
0
> (11%1) strictly_within a;
0
> 12 strictly_within a;
1
> (12%1) strictly_within a;
1
(The symbol a was defined in Example 36.)
Some standard functions are overloaded for intervals; some new functions are provided.
abs v
Example 40 Absolute interval:
> abs (interval (1, 5));
interval::Ivl 1 5
> abs (interval (-1, 5));
interval::Ivl 0 5
> abs (interval (-5, -1));
interval::Ivl 1 5
sgn v
# v
Example 41 Absolute interval:
> #d;
4
(The symbol d was defined in Example 36.)
rational::rational_approx_epsilon ε r
Example 42 Rational approximation to π ≈ 3.142 ≈ 22/7:
> rational_approx_epsilon .01 pi;
22L%7L
> abs (ans - pi);
0.00126448926734968
Example 43 The golden ratio φ = (1 + √5) / 2 ≈ 1.618:
> let phi = (1 + sqrt 5) / 2;
> rational_approx_epsilon .001 phi;
55L%34L
> abs (ans - phi);
0.000386929926365465
rational::rational_approxs_epsilon ε r
Example 44 Rational approximations to π:
> rational_approxs_epsilon .0001 pi;
[3L%1L,25L%8L,47L%15L,69L%22L,91L%29L,113L%36L,135L%43L,157L%50L,179L%57L,
201L%64L,223L%71L,245L%78L,267L%85L,289L%92L,311L%99L,333L%106L]
Example 45 Rational approximations to the golden ratio φ; these approximations are always reverse consecutive Fibonacci numbers (from f1: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …):
> rational_approxs_epsilon .0001 phi;
[1L%1L,3L%2L,8L%5L,21L%13L,55L%34L,144L%89L]
(The symbol phi was defined in Example 43.)
rational::rational_interval_epsilon ε r
Example 46 Rational interval surrounding π:
> let i_Pi = rational_interval_epsilon .01 pi;
> i_Pi;
interval::Ivl (47L%15L) (22L%7L)
> double (lower i_Pi); pi; double (upper i_Pi);
3.13333333333333
3.14159265358979
3.14285714285714
(The functions lower and upper are described in Interval Constructors and ‘Deconstructors’.)
Example 47 Rational interval surrounding the golden ratio φ:
> rational_interval_epsilon .001 phi;
interval::Ivl (55L%34L) (89L%55L)
> #ans;
1L%1870L
(The symbol phi was defined in Example 43. The function #
is described in Interval Maths.)
rational::rational_approx_max_den maxDen r
Example 48 Rational approximation to π:
> rational_approx_max_den 10 pi;
22L%7L
Example 49 Rational approximation to the golden ratio φ:
> rational_approx_max_den 1000 phi;
1597L%987L
(The symbol phi was defined in Example 43.)
rational::rational_approxs_max_den maxDen r
Example 50 Rational approximations to π:
> rational_approxs_max_den 100 pi;
[3L%1L,25L%8L,47L%15L,69L%22L,91L%29L,113L%36L,135L%43L,157L%50L,179L%57L,
201L%64L,223L%71L,245L%78L,267L%85L,289L%92L,311L%99L]
Example 51 Rational approximations to the golden ratio φ:
> rational_approxs_max_den 100 phi;
[1L%1L,3L%2L,8L%5L,21L%13L,55L%34L,144L%89L]
(The symbol phi was defined in Example 43.)
rational::rational_interval_max_den maxDen r
Example 52 Rational interval surrounding π:
> let i_Pi = rational_interval_max_den 100 pi ; i_Pi;
interval::Ivl (311L%99L) (22L%7L)
> double (lower i_Pi); pi; double (upper i_Pi);
3.14141414141414
3.14159265358979
3.14285714285714
Example 53 Rational interval surrounding the golden ratio φ:
> rational_interval_max_den 1000 phi;
interval::Ivl (987L%610L) (1597L%987L)
(The symbol phi was defined in Example 43.)
To approximate for a particular (rather than bounded) denominator, use round to multiple instead (see Rounding to Multiples).
There is more than one way to ‘decompose’ a rational number into its ‘components’. It might be split into an integer and a fraction part — see Integer and Fraction Parts; or sign and absolute value — see Absolute Value and Sign; or numerator and denominator — see ‘Deconstructors’.
In “pure-rational”, a continued fraction a0 + (1 / (a1 + (1 / (a2 + ··· + 1 / a n)))) where ∀i > 0 • ai ≠ 0, is represented by [a0, a 1, a2, … , an].
A ‘simple’ continued fraction is one in which ∀i • ai ∈ Z and ∀i > 0 • ai > 0.
Simple continued fractions for rationals are not quite unique since [a 0, a1, … , an, 1] = [a0, a1, … , an+1]. We will refer to these as the ‘non-standard’ and ‘standard’ forms, respectively. The following functions return the standard form.
rational::continued_fraction q
Example 54 The rational 1234/1001:
> continued_fraction (1234%1001);
[1L,4L,3L,2L,1L,1L,1L,8L]
> evaluate_continued_fraction ans;
1234L%1001L
rational::continued_fraction_max_terms n r
Example 55 First 5 terms of the continued fraction for the golden ratio φ:
> continued_fraction_max_terms 5 phi;
[1.0,1.0,1.0,1.0,1.0,1.61803398874989]
> evaluate_continued_fraction ans;
1.61803398874989
(The symbol phi was defined in Example 43.)
rational::continued_fraction_epsilon ε r
Example 56 First few terms of the value √2:
> continued_fraction_epsilon .001 (sqrt 2);
[1.0,2.0,2.0,2.0,2.0,2.41421356237241]
> map double (convergents ans);
[1.0,1.5,1.4,1.41666666666667,1.41379310344828,1.41421356237309]
rational::evaluate_continued_fraction aa
Example 57 The continued fraction [1, 2, 3, 4] and the non-standard form [4, 3, 2, 1]:
> evaluate_continued_fraction [1,2,3,4];
43L%30L
> continued_fraction ans;
[1L,2L,3L,4L]
> evaluate_continued_fraction [4,3,2,1];
43L%10L
> continued_fraction ans;
[4L,3L,3L]
rational::convergents aa
Example 58 Convergents of a continued fraction approximation of the value √2:
> continued_fraction_max_terms 5 (sqrt 2);
[1.0,2.0,2.0,2.0,2.0,2.41421356237241]
> convergents ans;
[1.0,1.5,1.4,1.41666666666667,1.41379310344828,1.41421356237309]
Pure together with rational.pure
provide various types of number, including integers (Z), doubles (R, roughly), complex numbers (C) and Gaussian integers (Z[i]), rationals (Q) and rational complex numbers (Q[i]).
Functions concerning ‘complex numbers’ are named with ‘comp’, whereas functions concerning ‘complexity’ (see Complexity) are named with ‘cplx’.
Complex numbers can have rational parts.
Example 59 Forming a rational complex:
> 1 +: 1 * (1%2);
1+:1L%2L
> ans * ans;
3L%4L+:1L%1L
And rational numbers can be given complex parts.
Example 60 Complex rationals and complicated rationals:
> (1 +: 2) % (3 +: 4);
11L%25L+:2L%25L
> ans * (3 +: 4);
1L%1L+:2L%1L
> ((4%1) * (0 +: 1)) % 2;
0L%1L+:2L%1L
> ((4%1) * (0 +: 1)) % (1%2);
0L%1L+:8L%1L
> ((4%1) * (0 +: 1)) % (1 + (1%2) * (0 +: 1));
8L%5L+:16L%5L
> ans * (1+(1%2) * (0 +: 1));
0L%1L+:4L%1L
> ((4%1) * (0 +: 1)) / (1 + (1%2) * (0 +: 1));
1.6+:3.2
The various parts of a complex rational may be deconstructed using combinations of num and den and the standard functions re and im.
Thus, taking real and imaginary parts first, a rational complex number may be considered to be (xn / xd) + (yn / yd) * i with xn, xd, yn, yd ∈ Z.
A rational complex number may also be decomposed into its ‘numerator’ and ‘denominator’, where these are both integral complex numbers, or ‘Gaussian integers’, and the denominatoris a minimal choice in some sense.
One way to do this is so that the denominator is the minimum positive integer. The denominator is a complex number with zero imaginary part.
Thus, taking numerator and denominator parts first, a rational complex number may be considered to be (nx + ny * i) / (d + 0 * i) with n x, ny, d ∈ Z.
Another way to do this is so that the denominator is a Gaussian integer with minimal absolute value. Thus, taking numerator and denominator parts first, a rational complex number may be considered to be (nx + ny * i) / (dx + dy * i) with nx, ny, dx, d y ∈ Z.
The dx, dy are not unique, but can be chosen such that d x > 0 and either |dy| < dx or dy = d x > 0.
rational::num_den_nat c
given a complex rational or integer c, returns a pair (n, d) containing an integral complex (Gaussian integral) numerator n, and the smallest natural (i.e. positive integral real) complex denominator d, i.e. a complex number where ℜ(d) ∈ Z, ℜ(d) > 0, ℑ(d) = 0; i.e. the numerator and denominator of one ‘normalised’ form of c.
This is an inverse (up to equivalence) of rational as defined on integral complex pairs (see Constructors).
rational::num_den_gauss c
given a complex rational or integer c, returns a pair (n, d) containing an integral complex (Gaussian integral) numerator n, and an absolutely smallest integral complex denominator d chosen s.t. ℜ(d),=(d) ∈ Z, ℜ(d) > 0, and either |ℜ(d)| < ℑ(d) or ℜ(d) = ℑ(d) > 0; i.e. the numerator and denominator of another ‘normalised’ form of c.
This is an inverse (up to equivalence) of rational as defined on integral complex pairs (see Constructors).
rational::num_den c
synonymous with num_den_gauss.
This is an inverse (up to equivalence) of rational as defined on integer pairs (see Constructors).
num c
den c
Example 61 Rational complex number deconstruction:
> let cq = (1+2*i)%(3+3*i); cq;
1L%2L+:1L%6L
> (re cq, im cq);
1L%2L,1L%6L
> (num . re) cq;
1L
> (den . re) cq;
2L
> (num . im) cq;
1L
> (den . im) cq;
6L
> let (n_nat,d_nat) = num_den_nat cq;
> (n_nat, d_nat);
3+:1,6+:0
> n_nat % d_nat;
1L%2L+:1L%6L
> abs d_nat;
6.0
> let (n, d) = num_den_gauss cq; (n, d);
1L+:2L,3L+:3L
> let (n,d) = num_den cq; (n, d);
1L+:2L,3L+:3L
> n % d;
1L%2L+:1L%6L
> abs d;
4.24264068711928
> (re . num) cq;
1L
> (im . num) cq;
2L
> (re . den) cq; //always > 0
3L
> (im . den) cq; //always <= (re.den)
3L
Beware that intcompvalp
and ratcompvapl
may return 1 even if the value is of complex type with double parts. However, these functions may be combined with exactp
.
complexp x
compvalp x
rational::ratcompvalp x
rational::intcompvalp x
Example 62 Rational complex number value tests:
> let l = [9, 9%1, 9%2, 4.5, sqrt 2, 1+:1, 1%2+:1, 0.5+:1, inf, nan];
> map exactp l;
[1,1,1,0,0,1,1,0,0,0]
> map inexactp l;
[0,0,0,1,1,0,0,1,1,1]
> map complexp l;
[0,0,0,0,0,1,1,1,0,0]
> map compvalp l;
[1,1,1,1,1,1,1,1,1,1]
> map (\x -> (exactp x and compvalp x)) l; // "has exact complex value"
[1,1,1,0,0,1,1,0,0,0]
> map ratcompvalp l;
[1,1,1,1,1,1,1,1,0,0]
> map (\x -> (exactp x and ratcompvalp x)) l;
[1,1,1,0,0,1,1,0,0,0]
> map intcompvalp l;
[1,1,0,0,0,1,0,0,0,0]
> map (\x -> (exactp x and intcompvalp x)) l;
[1,1,0,0,0,1,0,0,0,0]
> map ratvalp l;
[1,1,1,1,1,0,0,0,0,0]
> map (\x -> (exactp x and ratvalp x)) l;
[1,1,1,0,0,0,0,0,0,0]
> map intvalp l; // for comparison
[1,1,0,0,0,0,0,0,0,0]
> map (\x -> (exactp x and intvalp x)) l;
[1,1,0,0,0,0,0,0,0,0]
See `Type and Value Tests`_ for some details of rational type and value tests.
The standard arithmetic operators (+), (−), (*), (/), (%), (), (==) and (~=) are overloaded to have at least one complex and/or rational operand, but (<), (<=), (>), (>=) are not, as complex numbers are unordered.
Example 63 Rational complex arithmetic:
> let w = 1%2 +: 3%4;
> let z = 5%6 +: 7%8;
> w + z;
4L%3L+:13L%8L
> w % z;
618L%841L+:108L%841L
> w / z;
0.734839476813318+:0.128418549346017
> w ^ 2;
-0.3125+:0.75
> w == z;
0
> w == w;
1
The standard functions re
and im
work with rational complex numbers (see Rational Complex Constructors and ‘Deconstructors’).
The standard functions polar
, abs
and arg
work with rational complex numbers, but the results are inexact.
Example 64 Rational complex maths:
> polar (1%2+:1%2);
0.707106781186548<:0.785398163397448
> abs (4%2+:3%2);
2.5
> arg (-1%1);
3.14159265358979
There are some additional useful functions for calculating with rational complex numbers and more general mathematical values.
rational::norm_gauss c
rational::div_mod_gauss n d
rational::n_div_gauss d
rational::n_mod_gauss d
rational::gcd_gauss c1 c2
rational::euclid_gcd zerofun modfun x y
rational::euclid_alg zerofun divfun x y
Example 65 More rational complex and other maths:
> norm_gauss (1 +: 3);
10
> abs (1 +: 3);
3.16227766016838
> norm_gauss (-5);
25
> let (q, r) = div_mod_gauss 100 (12 +: 5);
> (q, r);
7L+:-3L,1L+:1L
> q * (12 +: 5) + r;
100L+:0L
> 100 div_gauss (12 +: 5);
7L+:-3L
> 100 mod_gauss (12 +: 5);
1L+:1L
> div_mod_gauss 23 5;
5L+:0L,-2L+:0L
> gcd_gauss (1 +: 2) (3 +: 4);
1L+:0L
> gcd_gauss 25 15;
5L+:0L
> euclid_gcd (==0) (mod_gauss) (1+: 2) (3 +: 4);
1L+:0L
> euclid_gcd (==0) (mod) 25 15;
5
> let (g, a, b) = euclid_alg (==0) (div_gauss) (1 +: 2) (3 +: 4); g;
1L+:0L
> (a, b);
-2L+:0L,1L+:0L
> a * (1 +: 2) + b * (3 +: 4);
1L+:0L
> let (g, a, b) = euclid_alg (==0) (div) 25 15; g;
5
> (a, b);
-1,2
> a * 25 + b * 15;
5
rational::comp_simplify c
rational::ratcomp_simplify c
Example 66 Rational complex number type simplification:
> let l = [9+:1, 9%1+:1, 9%2+:1, 4.5+:1, 9%1+:0, 9%2+:0, 4.5+:0.0];
> l;
[9+:1,9L%1L+:1,9L%2L+:1,4.5+:1,9L%1L+:0,9L%2L+:0,4.5+:0.0]
> map comp_simplify l;
[9+:1,9L%1L+:1,9L%2L+:1,4.5+:1,9L%1L,9L%2L,4.5+:0.0]
> map ratcomp_simplify l;
[9+:1,9+:1,9L%2L+:1,4.5+:1,9,9L%2L,4.5+:0.0]
See `Rational Type Simplification`_ for some details of rational type
simplification.
There are several families of functions for converting between strings and rationals.
The functions that convert from rationals to strings have names based on that of the standard function str
. The str_*
functions convert to a formatted string, and depend on a ‘format structure’ parameter (see Internationalisation and Format Structures). The strs_*
functions convert to a tuple of string fragments.
The functions that convert from strings to rationals have names based on that of the standard function eval
(val
in Q). The val_*
functions convert from a formatted string, and depend on a format structure parameter. The sval_*
functions convert from a tuple of string fragments.
There are also join_*
and split_*
functions to join string fragments into formatted strings, and to split formatted strings into string fragments, respectively; these depend on a format structure parameter. These functions are not always invertible, because some of the functions reduce an error term to just a sign, e.g. str_real_approx_dp
may round a value. Thus sometimes the join_*
and split_*
pairs, and the str_*
and val_*
pairs are not quite mutual inverses.
Many of the string formatting functions in the following sections are parameterised by a ‘format structure’. Throughout this document, the formal parameter for the format structure will be fmt
. This is simply a record mapping some string ‘codes’ to functions as follows. The functions are mostly from strings to a string, or from a string to a tuple of strings.
"sm"
a function mapping a sign and an unsigned mantissa (or integer) strings to a signed mantissa (or integer) string.
"se"
a function mapping a sign and an unsigned exponent string to a signed exponent string.
"-s"
a function mapping a signed number string to a pair containing a sign and the unsigned number string.
"gi"
a function mapping an integer representing the group size and an integer string to a grouped integer string.
"gf"
a function mapping an integer representing the group size and a fraction-part string to a grouped fraction-part string.
"-g"
a function mapping a grouped number string to an ungrouped number string.
"zi"
a function mapping an integer number string to a number string. The input string representing zero integer part is “”, which should be mapped to the desired representation of zero. All other number strings should be returned unaltered.
"zf"
a function mapping a fraction-part number string to a number string. The input string representing zero fraction part is “”, which should be mapped to the desired representation of zero. All other number strings should be returned unaltered.
"ir"
a function mapping initial and recurring parts of a fraction part to the desired format.
"-ir"
a function mapping a formatted fraction part to the component initial and recurring parts.
"if"
a function mapping an integer string and fraction part string to the radix-point formatted string.
"-if"
a function mapping a radix-point formatted string to the component integer fraction part strings
"me"
a function mapping a mantissa string and exponent string to the formatted exponential string.
"-me"
a function mapping a formatted exponential string to the component mantissa and exponent strings.
"e"
a function mapping an ‘error’ number (not string) and a number string to a formatted number string indicating the sign of the error.
"-e"
a function mapping a formatted number string indicating the sign of the error to the component ‘error’ string (not number) and number strings.
Depending upon the format structure, some parameters of some of the functions taking a format structure may have no effect. For example, an intGroup
parameter specifying the size of the integer digit groups will have no effect if the integer group separator is the empty string.
rational::create_format options
For example, format_uk
is generated from options_uk
as follows:
public options_uk;
const options_uk =
{
"sign" => ("-","",""), // alternative: ("-"," ","+")
"exponent sign" => ("-","",""), // alternative: ("-","","+")
"group separator" => ",", // might be " " or "." or "'" elsewhere
"zero" => "0",
"radix point" => ".", // might be "," elsewhere
"fraction group separator" => ",",
"fraction zero" => "0", // alternative: ""
"recur brackets" => ("[","...]"),
"exponent" => "*10^", // (poor) alternative: "e"
"error sign" => ("-","","+"),
"error brackets" => ("(",")")
};
public format_uk;
const format_uk = create_format options_uk;
The exponent string need not depend on the radix, as the numerals for the number radix in that radix are always “10”.
Beware of using “e” or “E” as an exponent string as these have the potential of being treated as digits in, e.g., hexadecimal.
Format structures do not have to be generated via create format; they may also be constructed directly.
Some functions take group
parameters. A value of 0 means “don’t group”.
The functions that produce a decimal expansion take a Radix argument. The fraction parts are expanded in that radix (or ‘base’), in addition to the integer parts. The parameter Radix is not restricted to the usual {2, 8, 10, 16}, but may be any integer from 2 to 36; the numerals (‘digits’) are chosen from [“0”, … , “9”, “A”, … , “Z”]. The letter-digits are always upper case.
The functions do not attach a prefix (such as “0x” for hexadecimal) to the resulting string.
Some functions return a value including an ‘error’ term (in a tuple) or sign (at the end of a string). Such an error is represents what the next digit would be as a fraction of the radix.
Example 67 Error term in the tuple of string ‘fragments’:
> strs_real_approx_sf 10 floor 3 (234567%100000);
"+","2","34",567L%1000L
> strs_real_approx_sf 10 ceil 3 (234567%100000);
"+","2","35",(-433L)%1000L
(See the function strs_real_approx_sf
.)
In strings, only the sign of the error term is given. A “+” should be read as “and a bit more”; “-” as “but a bit less”.
Example 68 Error sign in the string:
> str_real_approx_sf format_uk 10 0 0 floor 3 (234567%100000);
"2.34(+)"
> str_real_approx_sf format_uk 10 0 0 ceil 3 (234567%100000);
"2.35(-)"
(See the function str_real_approx_sf
.)
rational::str_vulgar q
returns a String representing the rational (or integer) q in the form
rational::str_vulgar_or_int q
returns a String representing the rational (or integer) q in one of the forms
rational::str_mixed q
returns a String representing the rational (or integer) q in one of the forms
Example 69 The fraction string representations:
> let l = iterwhile (<= 3%2) (+(1%2)) (-3%2);
> l;
[(-3L)%2L,(-1L)%1L,(-1L)%2L,0L%1L,1L%2L,1L%1L,3L%2L]
> map str_vulgar l;
["-3L/2L","-1L/1L","-1L/2L","0L/1L","1L/2L","1L/1L","3L/2L"]
> map str_vulgar_or_int l;
["-3L/2L","-1L","-1L/2L","0L","1L/2L","1L","3L/2L"]
> map str_mixed l;
["-(1L+1L/2L)","-1L","-1L/2L","0L","1L/2L","1L","1L+1L/2L"]
These might be compared to the behaviour of the standard function str
.
str x
Example 70 The standard function str:
> map str l;
["(-3L)%2L","(-1L)%1L","(-1L)%2L","0L%1L","1L%2L","1L%1L","3L%2L"]
rational::val_vulgar strg
returns a rational q represented by the string strg in the form
Such strings can also be evaluated by the val_mixed
function.
rational::val_mixed strg
returns a rational q represented by the string strg
Example 71 Evaluating fraction strings:
> val_vulgar "-22/7";
(-22L)%7L
> val_mixed "1L+5L/6L";
11L%6L
These might be compared to the behaviour of the standard function eval.
eval s
Example 72 The standard function eval:
> eval "1+5%6";
11L%6L
> eval "1L+5L/6L";
1.83333333333333
See Internationalisation and Format Structures for information about the formatting structure to be supplied in the fmt
parameter.
rational::str_real_recur fmt radix intGroup q
returns a string (exactly) representing the rational (or integer) q as base-Radix expansion of one the forms
Note that there is no fracGroup parameter.
Beware that the string returned by this function can be very long. The length of the recurring part of such a decimal expansion may be up to one less than the simplest denominator of q.
Example 73 The recurring radix expansion-type string representations:
> str_real_recur format_uk 10 3 (4000001%4); // grouped with commas
"1,000,000.25"
> str_real_recur format_uk 10 0 (4000001%4); // no grouping
"1000000.25"
> str_real_recur format_uk 10 3 (1000000%3);
"333,333.[3...]"
> str_real_recur format_uk 10 3 (1000000%7);
"142,857.[142857...]"
> str_real_recur format_uk 10 3 (-1%700);
"-0.00[142857...]"
> str_real_recur format_uk 10 3 (127%128);
"0.9921875"
> str_real_recur format_uk 2 4 (-127%128);
"-0.1111111"
> str_real_recur format_uk 16 4 (127%128);
"0.FE"
> str_real_recur format_uk 10 0 (70057%350); // 1%7 + 10001%50;
"200.16[285714...]"
The function allows expansion to different radices (bases).
Example 74 The recurring radix expansion in decimal and hexadecimal:
> str_real_recur format_uk 10 0 (1%100);
"0.01"
> str_real_recur format_uk 16 0 (1%100);
"0.0[28F5C...]"
Example 75 The recurring radix expansion in duodecimal:
> str_real_recur format_uk 12 0 (1%100);
"0.0[15343A0B62A68781B059...]"
Note that this bracket notation is not standard in the literature. Usually the recurring numerals are indicated by a single dot over the initial and final numerals of the recurring part, or an overline over the recurring part. For example 1/70 = 0.0˙14285˙7 = 0.0142857 and 1/3 = 0.˙3 = 0.3.
rational::strs_real_recur radix q
returns a quadruple of the four strings:
Example 76 The recurring radix expansion in decimal — the fragments:
> strs_real_recur 10 (100%7);
"+","14","","285714"
> strs_real_recur 10 (-1%700);
"-","","00","142857"
> strs_real_recur 10 (70057%350);
"+","200","16","285714"
This function may be used to also, e.g. format the integer part with comma-separated groupings.
rational::join_str_real_recur fmt intGroup sign i fracInit fracRecur
strs_real_recur
to the sort of string as returned by str_real_recur
.
The str_*
and val_*
functions depend on a ‘format structure’ parameter (fmt) such as format uk. Conversions may be performed between rationals and differently formatted strings if a suitable alternative format structure is supplied. See Internationalisation and Format Structures for information about formatting structures.
rational::val_real_recur fmt radix strg
returns the rational q represented by the base-radix expansion string strg of one the forms
Example 77 Conversion from the recurring radix expansion-type string representations:
> val_real_recur format_uk 10 "-12.345";
(-2469L)%200L
> val_real_recur format_uk 10 "0.3";
3L%10L
> val_real_recur format_uk 10 "0.[3...]";
1L%3L
> val_real_recur format_uk 10 ".333[33...]";
1L%3L
> val_real_recur format_uk 10 ".[9...]";
1L%1L
rational::sval_real_recur radix sign iStr fracStr recurPartStr
returns the rational q represented by the parts
rational::split_str_real_recur Fmt strg
returns a tuple containing the parts
See Internationalisation and Format Structures for information about the formatting structure to be supplied in the fmt
parameter.
The exponent string “*10^” need not depend on the radix, as the numerals for the number radix in that radix are always “10”.
rational::str_real_approx_dp fmt radix intGroup fracGroup roundfun dp q
roundfun
(see Rounding to Integer) roundfun
is usually round
or round_unbiased
. (dp may be positive, zero or negative; non-positive dps may look misleading — use e.g. scientific notation instead.)
Example 78 Decimal places:
> str_real_approx_dp format_uk 10 3 3 round 2 (22%7);
"3.14(+)"
> str_real_approx_dp format_uk 10 3 3 ceil 2 (22%7);
"3.15(-)"
rational::strs_real_approx_dp radix roundfun do q
returns a tuple of strings
representing an expansion to a number of decimal places, together with
Example 79 Decimal places — the fragments:
> strs_real_approx_dp 10 round 2 (22%7);
"+","3","14",2L%7L
> strs_real_approx_dp 10 ceil 2 (22%7);
"+","3","15",(-5L)%7L
rational::join_str_real_approx fmt intGroup fracGroup sign i frac err
strs_real_approx_dp
or strs_real_approx_sf
to the sort of string as returned by str_real_approx_dp
or str_real_approx_sf
.
rational::str_real_approx_sf fmt radix intGroup fracGroup roundfun sf q
roundfun
(see Rounding to Integer).
roundfun
is usually round
or round_unbiased
. (sf must be positive.)
Example 80 Significant figures:
> str_real_approx_sf format_uk 10 3 3 floor 2 (22%7);
"3.1(+)"
> str_real_approx_sf format_uk 10 3 3 floor 2 ((-22)%7);
"-3.2(+)"
rational::strs_real_approx_sf radix roundfun sf q
returns a tuple of strings
join_str_real_approx
join_str_real_approx
.
rational::str_real_approx_sci fmt radix intGroup fracGroup roundfun sf q
returns a string expansion with a number of significant figures in scientific notation, using rounding mode roundfun
(see Rounding to Integer).
(sf must be positive; expStep is usually 3, radix is usually 10, roundfun
is usually round
or round_unbiased
; str_real_approx_sci
is equivalent to str_real_approx_eng
(below) with expStep = 1.)
rational::strs_real_approx_sci radix roundfun sf q
returns a tuple of strings:
representing an expansion to a number of significant figures in scientific notation together with
rational::str_real_approx_eng fmt expStep radix intGroup fracGroup round sf q
returns a string expansion with a number of significant figures in engineering notation, using rounding mode roundfun.
The ExpStep parameter specifies the granularity of the exponent; specifically, the exponent will always be divisible by expStep.
(sf must be positive; expStep is usually 3 and must be positive, radix is usually 10, roundfun
is usually round
or round_unbiased
.)
Example 81 Engineering notation:
> str_real_approx_eng format_uk 3 10 3 3 round 7 (rational 999950);
"999.950,0*10^3"
> str_real_approx_eng format_uk 3 10 3 3 round 4 999950;
"1.000*10^6(-)"
rational::strs_real_approx_eng expStep radix roundfun sf q
returns a tuple of strings:
representing an expansion to a number of significant figures in engineering notation together with
Example 82 Engineering notation — the fragments:
> strs_real_approx_eng 3 10 round 7 (rational 999950);
"+","999","9500","+","3",0L%1L
> strs_real_approx_eng 3 10 round 4 999950;
"+","1","000","+","6",(-1L)%20L
rational::join_str_real_eng fmt intGroup fracGroup mantSign mantI mantF rac expSign expI err
strs_real_approx_eng
or strs_real_approx_sci to the sort of string as returned by str_real_approx_eng
or str_real_approx_sci
.
The str_*
and val_*
functions depend on a ‘format structure’ parameter (fmt) such as format uk. Conversions may be performed between rationals and differently formatted strings if a suitable alternative format structure is supplied. See Internationalisation and Format Structures for information about formatting structures.
rational::val_real_eng fmt radix strg
returns the rational q represented by the base-radix expansion string strg of one the forms
Example 83 Conversion from the recurring radix expansion-type string representations:
> val_real_eng format_uk 10 "-12.345";
(-2469L)%200L
> val_real_eng format_uk 10 "-12.345*10^2";
(-2469L)%2L
rational::sval_real_eng radix signStr mantIStr mantF racStr expSignStr expStr
returns the rational q represented by the parts
rational::split_str_real_eng fmt strg
returns a tuple containing the string parts
of one the forms
These functions can deal with the fixed decimal places, the significant figures and the scientific notation in addition to the engineering notation.
This section describes functions to approximate by a rational a real number represented by a string. See R -> Q — Approximation for approximation by a rational of a double.
The str_*
and val_*
functions depend on a ‘format structure’ parameter (fmt) such as format uk. Conversions may be performed between rationals and differently formatted strings if a format structure is supplied. See Internationalisation and Format Structures for information about formatting structures.
rational::val_eng_approx_epsilon fmt radix epsilon strg
Find the least complex rational approximation q to the number represented by the base-radix expansion string str in one of the forms
that is ε-close. That is find a q such that |q − eval str| ≤ ε.
Example 84 Rational from a long string:
> let strg = "123.456,789,876,543,212,345,678,987,654,321*10^27";
> let x = val_real_eng format_uk 10 strg;
> x;
123456789876543212345678987654321L%1000L
> let q = val_eng_approx_epsilon format_uk 10 (1%100) strg;
> q;
1975308638024691397530863802469L%16L
> double (x - q);
0.0085
> str_real_approx_eng format_uk 3 10 3 3 round 30 q;
"123.456,789,876,543,212,345,678,987,654*10^27(+)"
> str_real_approx_eng format_uk 3 10 3 3 round 42 q;
"123.456,789,876,543,212,345,678,987,654,312,500,000,000*10^27"
> double q;
1.23456789876543e+029
rational::val_eng_interval_epsilon fmt radix epsilon strg
Find the least complex rational interval containing the number represented by the base-radix expansion string strg in one of the forms
that is “-small.
rational::val_eng_approx_max_den fmt radix maxDen strg
Find the closest rational approximation to the number represented by the base-rRadix expansion string strg in one of the forms
that has a denominator no greater than maxDen. (maxDen > 0)
rational::val_eng_interval_max_den fmt radix maxDen strg
Find the smallest rational interval containing the number represented by the base-radix expansion string strg in one of the forms
that has endpoints with denominators no greater than maxDen. (maxDen > 0)
Example 85 Other rationals from a long string:
> val_eng_approx_epsilon format_uk 10 (1%100) strg;
1975308638024691397530863802469L%16L
> val_eng_interval_epsilon format_uk 10 (1%100) strg;
interval::Ivl (3086419746913580308641974691358L%25L)
(3456790116543209945679011654321L%28L)
> val_eng_approx_max_den format_uk 10 100 strg;
9999999980000000199999998000000L%81L
> val_eng_interval_max_den format_uk 10 100 strg;
interval::Ivl 9999999980000000199999998000000L%81L
3456790116543209945679011654321L%28L