Scheme 找到哈代–;使用R5RS方案的Ramanujan编号。请提出习惯用法和计算方面的改进建议。

Scheme 找到哈代–;使用R5RS方案的Ramanujan编号。请提出习惯用法和计算方面的改进建议。,scheme,Scheme,我记得有一次去看电影 [Srinivasa Ramanujan]他生病的时候 在普特尼。我坐过出租车 1729号,并指出 在我看来,这个数字相当沉闷, 我希望这不是一场灾难 不祥之兆。“不,”他回答说, “这是一个非常有趣的数字;它 最小的数字是否可以表示为 两个不同立方体中两个立方体的和 方法。”[G.H.哈代,如中所述] 约瑟夫·塔塔科夫斯基在书中谈到这一壮举,“那又怎样? 给我两分钟和我的计算器手表,我也会这么做 我不知道该怎么做 塔塔科夫斯基先生会在一块计算器手表上完成这个证明,但是 下

我记得有一次去看电影 [Srinivasa Ramanujan]他生病的时候 在普特尼。我坐过出租车 1729号,并指出 在我看来,这个数字相当沉闷, 我希望这不是一场灾难 不祥之兆。“不,”他回答说, “这是一个非常有趣的数字;它 最小的数字是否可以表示为 两个不同立方体中两个立方体的和 方法。”[G.H.哈代,如中所述]

约瑟夫·塔塔科夫斯基在书中谈到这一壮举,“那又怎样? 给我两分钟和我的计算器手表,我也会这么做 我不知道该怎么做 塔塔科夫斯基先生会在一块计算器手表上完成这个证明,但是 下面是我的scheme函数,它枚举从 在1处,当它找到一个可表示为2的数字时停止 通过两个正数的立方体求和来分离方法。而且 索引返回1729

我希望在两个方面提出建议 改进。其中一个方面是,对方案、风格和习惯用法都不熟悉。另一个领域是计算。Sisc 不会返回根的确切数字,即使可能。对于 示例
(expt 27 1/3)
产生2.9999999996。但我确实知道 结果当对一个精确的数字进行立方运算时,
(expt 3)
产生
27
。我的 解决方案是得到一个立方根的确切楼层,然后进行测试 相对于地板的立方体和地板的立方体加上一, 如果其中一个匹配,则计算为匹配。这个解决方案看起来很混乱,也很难解释。有没有更直接的方法

; Find the Hardy-Ramanujan number, which is the smallest positive
; integer that is the sum of the cubes of two positivie integers in
; two seperate ways.
(define (hardy-ramanujan-number)
  (let ((how-many-sum-of-2-positive-cubes
          ; while i^3 + 1 < n/1
          ;     tmp := exact_floor(cube-root(n - i^3))
          ;     if n = i^3 + tmp^3 or n = i^3 + (tmp + 1) ^3 then count := count + 1
          ; return count
          (lambda (n)
            (let ((cube (lambda (n) (expt n 3)))
                  (cube-root (lambda (n) (inexact->exact (expt n 1/3)))))
              (let iter ((i 1) (count 0)) 
                (if (> (+ (expt i 3) 1) (/ n 2))
                    count
                    (let* ((cube-i (cube i))
                           (tmp (floor (cube-root (- n cube-i)))))
                      (iter (+ i 1)
                        (+ count
                          (if (or (= n (+ cube-i (cube tmp)))
                                  (= n (+ cube-i (cube (+ tmp 1)))))
                              1
                              0))))))))))
    (let iter ((n 1))
      (if (= (how-many-sum-of-2-positive-cubes n) 2)
          n
          (iter (+ 1 n))))))
;找到Hardy Ramanujan数,它是最小的正数
; 整数,是两个正整数的立方体之和
; 两种不同的方式。
(定义(hardy ramanujan编号)
(让((2个正立方体的数量和)
;而i^3+1精确(expt n 1/3‘‘‘)’))
(让国际热核实验堆((i 1)(计数0))
(如果(>(+(expt i3)1)(/n2))
计数
(让*((立方体一(立方体一))
(tmp(地板(立方根(-n立方体-i '))))
(国际热核实验堆(+i-1)
(+计数
(如果(或(=n(+cube-i(cube-tmp)))
(=n(+cube-i(cube(+tmp1()))))
1.
0))))))))))
(让iter((n 1))
(如果(=(2个正立方体的数量和n)2)
N
(国际热核实验堆(+1 n(()())))

您的代码看起来基本上很好,我看到一些非常小的问题需要评论:

  • 无需在最里面的范围内定义
    多维数据集
    多维数据集根

  • 对内部函数使用
    define
    ,使其看起来更清晰

  • 这与你问题的第二部分有关:你在浮点数上使用
    incexact->exact
    ,这会导致大的有理数(从分配两个大整数的意义上讲)——最好避免这种情况

  • 这样做仍然不能解决你所做的额外测试——但那只是因为你不确定你是否有正确的数字,如果你错过了1。考虑到它应该接近整数,您可以只使用
    舍入
    ,然后执行一次检查,从而节省一次测试

修复上述问题,并在一个函数中执行,该函数在找到数字时返回数字,并使用一些更“明显”的标识符名称,我得到以下结果:

(define (hardy-ramanujan-number n)
  (define (cube n) (expt n 3))
  (define (cube-root n) (inexact->exact (round (expt n 1/3))))
  (let iter ([i 1] [count 0])
    (if (> (+ (cube i) 1) (/ n 2))
      (hardy-ramanujan-number (+ n 1))
      (let* ([i^3   (cube i)]
             [j^3   (cube (cube-root (- n i^3)))]
             [count (if (= n (+ i^3 j^3)) (+ count 1) count)])
        (if (= count 2) n (iter (+ i 1) count))))))

我在Racket上运行这个程序,看起来快了大约10倍(50ms vs 5ms)。

不同的方案在精确求幂时表现不同:有些尽可能返回精确结果,有些在所有情况下都是不精确结果。您可以查看我的一组页面,看看哪些方案起到了什么作用。

+1感谢您不要过度设计您的解决方案。我本来打算写一个解决方案,对一些事情进行微观优化,但您的答案非常简洁,显然足够快。太简单了!