Exercise1-46 <---> Exercise2-2
Exercise 2.1.
Define a better version of make-rat that handles both positive and negative arguments. Make-rat should normalize the sign so that if the rational number is positive, both the numerator and denominator are positive, and if the rational number is negative, only the numerator is negative.
Ru: Определите улучшенную версию make-rat, которая принимала бы как положительные, так и отрицательные аргументы. Make-rat должна нормализовывать знак так, чтобы в случае, если рациональное число положительно, то и его числитель, и знаменатель были бы положительны, а если оно отрицательно, то чтобы только его числитель был отрицателен.
Scheme solution:
One of possible ways for transforming rational number to such canonical representational is to divide both numerator and denominator on signum of denominator. Then denominator will always be positive, as we need.
(define (gcd x y) ;; we've implemented gcd in section 1.2.5.
(if (= y 0)
x
(gcd y (remainder x y))))
(define (signum x)
(if (= 0 x)
0
(/ x (abs x))))
(define (make-rat n d)
(let ((g (gcd (abs n) (abs d)))
(s (signum d)))
(cons (/ n (* g s))
(/ d (* g s)))))
Haskell solution:
gcd x 0 = x -- gcd is a standard Prelude function
gcd x y = gcd y (x `mod` y)
signum x | x < 0 = -1 -- signum is a standard method of Prelude class Num
| x == 0 = 0
| x > 0 = 1
makeRat n d = (n `div` sg, d `div` sg)
where
g = gcd (abs n) (abs d)
sg = g * signum d
Oberon/Component Pascal solution:
TYPE Rational = POINTER TO RECORD
n, d : INTEGER
END;
PROCEDURE GCD (x, y : INTEGER) : INTEGER;
VAR a, b, c : INTEGER;
BEGIN
a := x; b := y;
WHILE b # 0 DO
c := a MOD b;
a := b; b := c
END;
RETURN a
END GCD;
PROCEDURE Signum (x : INTEGER) : INTEGER;
VAR s : INTEGER;
BEGIN
IF x < 0 THEN s := -1
ELSIF x = 0 THEN s := 0
ELSE s := 1
END;
RETURN s
END Signum;
PROCEDURE MakeRat (n, d : INTEGER) : Rational;
VAR g, sg : INTEGER;
r : Rational;
BEGIN
NEW (r);
g := GCD (ABS(n), ABS(d));
sg := g * Signum (d);
r.n := n DIV sg;
r.d := d DIV sg;
RETURN r
END MakeRat;
;; Another implementation.
;; lenatis@gmail.com
(define (make-rat N D)
(define (sign x)
(cond ((= x 0) 0)
(else (/ x (abs x)))))
(let ((S (sign (* N D))))
(cons (* S (abs N))
(abs D))))
Exercise1-46 <---> Exercise2-2
Comments
temporary disabled.