私はSICPを読んで、運動2.5やってるinconstantly動作します。私たちはペアを 我々は唯一の数字と算術演算を使用して非負 整数のペアを表すことができSICP行使2.5セレクタは
Exercise 2.5.表示を表している場合
a
製品番号2^a*3^b
である整数としてb
となります。 手順の対応する定義をcons
,car
, およびcdr
とします。
ここでは私のソリューションです:
;;; Exercise 2.5
;;; ============
(define (cons x y)
(* (expt 2 x)
(expt 3 y)))
(define (car z)
; n is a power of 2, which is greater than z
(let ((n (expt 2 (ceiling (/ (log z) (log 2))))))
(/ (log (gcd z n)) (log 2))))
(define (cdr z)
; n is a power of 3, which is greater than z
(let ((n (expt 3 (ceiling (/ (log z) (log 2))))))
(/ (log (gcd z n)) (log 3))))
私のコードは、比較的小規模なテストケースでうまく動作します。数が大きく成長したときに
(define x 12)
(define y 13)
(define z (cons x y))
(car z)
;Value: 12.
(cdr z)
;Value: 12.999999999999998
はしかし、それは間違った結果を生成します。
(define x 12)
(define y 14)
(define z (cons x y))
(car z)
;Value: 12.
(cdr z)
;Value: 2.8927892607143724 <-- Expected 14
何が問題なのか知りたい私の実装。アルゴリズムに問題はありますか?考えられるのは、z = 2^x * 3^y
とn
(2の累乗は、z
より大きい)という最も一般的なディベイヤは、正確には2^x
です。
私のアルゴリズムが正しい場合は、丸め誤差やオーバーフローによるこの矛盾ですか?
あなたの定義に非対称があり、間違っています。コピー&ペーストで 'cdr'を書いたと思います。 – molbdnilo
@molbdniloはい、私は彼らが類似していると思います。 'z = 2^x * 3^y'の場合、' log_2(z) 'は' '(car)'と '' cdr''の両方で '' ceiling(/(log 2) log_3(z)は 'y'よりも大きいことが保証されているだけです。 –
@SunQingyao私は 'cdr'の定義で' 2'を '3'に変更しましたが、実際には2.89ではなく14.0になりましたので効果があるようです。 – Sylwester