Use the supplied pointer-to-record representation and allocate a fresh record:
PROCEDURE mkRat(n,d: INTEGER): rational;
VAR z: rational;
BEGIN
ASSERT(d # 0);
NEW(z); z.num := n; z.den := d;
reduce(z);
RETURN z
END mkRat;The rational number constructor returns a value with positive denominator in lowest terms, using part (b). Zero is represented as . Arithmetic below uses exact integers, or inputs whose intermediate values fit the chosen implementation; fixed-width overflow would otherwise invalidate exact arithmetic.
PROCEDURE reduce(x: rational);
VAR g: INTEGER;
BEGIN
ASSERT(x.den # 0);
g := gcd(ABS(x.num),ABS(x.den));
x.num := x.num DIV g; x.den := x.den DIV g;
IF x.den < 0 THEN
x.num := -x.num; x.den := -x.den
END
END reduce;The denominator condition ensures , including when the numerator is zero. Dividing both components by the same nonzero integer preserves the fraction, and the final simultaneous sign change preserves it again. The resulting numerator and denominator are coprime; for zero the denominator becomes one.
Use the ordinary fraction identities, returning fresh records rather than changing either argument:
PROCEDURE addRat(x,y: rational): rational;
BEGIN
RETURN mkRat(x.num*y.den + y.num*x.den, x.den*y.den)
END addRat;
PROCEDURE mulRat(x,y: rational): rational;
BEGIN
RETURN mkRat(x.num*y.num, x.den*y.den)
END mulRat;
PROCEDURE negRat(x: rational): rational;
BEGIN
RETURN mkRat(-x.num,x.den)
END negRat;Every result is reduced by
mkRat. This preserves the representation invariant even if an input was initially unreduced, provided its denominator is nonzero. Aliasing between the arguments causes no problem because their fields are only read.Represent by the pair in the quadratic field . Its multiplication rule isThe constructor copies both rational components, so later reduction through another pointer cannot change the constructed value:
PROCEDURE mkIrr(r,i: rational): irrational;
VAR z: irrational;
BEGIN
NEW(z);
z.rat := mkRat(r.num,r.den);
z.irr := mkRat(i.num,i.den);
RETURN z
END mkIrr;
PROCEDURE addIrr(x,y: irrational): irrational;
BEGIN
RETURN mkIrr(addRat(x.rat,y.rat),addRat(x.irr,y.irr))
END addIrr;
PROCEDURE mulIrr(x,y: irrational): irrational;
VAR r,i: rational;
BEGIN
r := addRat(mulRat(x.rat,y.rat),
mulRat(mkRat(5,1),mulRat(x.irr,y.irr)));
i := addRat(mulRat(x.rat,y.irr),mulRat(x.irr,y.rat));
RETURN mkIrr(r,i)
END mulIrr;The representation includes rational values when the second coefficient is zero; the supplied type name does not require every stored value to be irrational.
First normalize fresh copies of the two components. The following output helpers print a reduced rational with no
/1, suppress a zero radical term, and suppress a unit radical coefficient:OutRat(q):
Out.Int(q.num)
if q.den != 1: Out.String("/"); Out.Int(q.den)
OutIrr(x):
r = mkRat(x.rat.num,x.rat.den)
b = mkRat(x.irr.num,x.irr.den)
if b.num == 0:
OutRat(r); return
if r.num != 0: OutRat(r)
if b.num < 0: Out.String("-")
else if r.num != 0: Out.String("+")
c = mkRat(abs(b.num),b.den)
if c.num != c.den:
OutRat(c); Out.String("*")
Out.String("sqrt(5)")Thus the examples print
1/2+1/2*sqrt(5) and 2; zero prints 0, and pure unit radicals print sqrt(5) or -sqrt(5). The positive-denominator invariant makes the coefficient sign test reliable. Input records are not mutated.Use Binet's formula entirely within . SetHere pairs mean the rational and radical coefficients. An exact program using the preceding procedures is
z = mkRat(0,1); one = mkRat(1,1)
half = mkRat(1,2)
phi = mkIrr(half,half)
psi = mkIrr(half,negRat(half))
c = mkIrr(z,mkRat(1,5))
p = mkIrr(one,z); q = mkIrr(one,z)
for i = 0,...,n-1:
minusQ = mkIrr(negRat(q.rat),negRat(q.irr))
OutIrr(mulIrr(c,addIrr(p,minusQ)))
Out.Ln()
p = mulIrr(p,phi)
q = mulIrr(q,psi)At iteration , and , so the printed value is exactly . The irrational coefficient cancels algebraically, and the rational result is an integer. This prints ; to use the convention , initialize
p=phi and q=psi. There are field operations, with growing arbitrary-precision arithmetic costs kept separate from that count. Articles by others on the same topic
There are currently no matching articles.