Сделать версию сделать-крыса, которая обрабатывает положительные и отрицательные аргументы


Дана следующая задача из SICP

Упражнение 2.1

Определить лучшую версию мейк-крыса, который обрабатывает оба положительные и отрицательных аргументов. Сделать-крыса следует нормализовать знак, так что если рациональное число является положительным, как числитель и знаменатель положительно, и если рациональное число отрицательно, только числитель отрицательно.

И эти функции условие:

(define (gcd a b) (if (= b 0) a (gcd b (remainder a b))))

(define (numer a) (car a))
(define (denom a) (cdr a))
(define (print-rat a)
  (newline)
  (display (numer a))
  (display "/")
  (display (denom a)))

(define (add-rat a b)
  (make-rat (+ (* (numer a) (denom b))
               (* (numer b) (denom a)))   
            (* (denom a) (denom b))))
(define (sub-rat a b)
  (make-rat (- (* (numer a) (denom b))
               (* (numer b) (denom a)))

            (* (denom a) (denom b))))
(define (mul-rat a b)
  (make-rat (* (numer a) (numer b))
            (* (denom a) (denom b))))
(define (div-rat a b)
  (make-rat (* (numer a) (denom b))
            (* (numer b) (denom a))))

Я написал эту версию (сделать-крысы ... ). Что вы думаете?

(define (make-rat n d)
  (define (sign n d) (if (> (* n d) 0) + -))
  (let* ((abs-n (abs n)) 
         (abs-d (abs d)) 
         (div (gcd abs-n abs-d)))
    (cons ((sign n d) (/ abs-n div)) 
          (/ abs-d div))))


566
2
задан 1 апреля 2011 в 04:04 Источник Поделиться
Комментарии
1 ответ

Чтобы нормализовать долю, нужно сделать две вещи:


  1. исправить знаки числителя и знаменателя; и

  2. уменьшить их до минимальных сроков.

Ваша реализация делает эти две вещи просто отлично. Однако, есть более простой способ. Чтобы сделать (1), просто отрицают оба числителя и знаменателя, если делитель отрицательный. Делать (2), разделить на наибольший общий делитель.

Можно объединить два вышеперечисленных шагов. Разделив числитель и знаменатель на наибольший общий делитель ее вывеску, чтобы быть таким же, как знак знаменателя это. Реализация следующая:

(define (make-rat n d)
(let
((div ((if (< d 0) - +) (abs (gcd n d)))))
(cons (/ n div) (/ d div))))

Если НОД всегда возвращает положительное число (которое ваша реализация не делает), вы можете удалить вызов АБС выше.

2
ответ дан 2 апреля 2011 в 03:04 Источник Поделиться