我记得有一次会去看 [Srinivasa Ramanujan]生病时 在普特尼。我乘坐出租车 号码1729,并评论说 在我看来,数字相当沉闷, 我希望它不是一个 不利的预兆。 “不,”他回答说, “这是一个非常有趣的数字;它 是可表达的最小数字 两个不同的立方体的总和 方式。“[G. H. Hardy在"1729 (number)"中说道]
在"Math Wrath"约瑟夫·塔尔塔科夫斯基谈到这一壮举,“那又怎样? 给我两分钟和我的计算器表,我也会这样做 没有施加任何小灰色细胞。“我不知道怎么做 Tartakovsky先生将在计算器手表上完成这一证明,但是 以下是我的计划函数,它枚举数字开头 在1处,当它找到一个可以用两个表示的数字时停止 通过对两个正数的立方体求和来分离。它 契约返回1729年。
有两个方面我会很感激
改进。一个领域是,对计划,风格和习语不熟悉。另一个区域是围绕计算。 SISC
根本没有返回确切的数字,即使它们可能。对于
示例(expt 27 1/3)
产生2.9999999999999996。但我确实得到了
当一个确切的数字成立时,(expt 3 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))))))
答案 0 :(得分:6)
你的代码看起来很好,我看到一些非常小的评论内容:
无需在最里层范围内定义cube
和cube-root
,
使用define
作为内部函数使其看起来更清晰,
这与你问题的第二部分有关:你在浮点数上使用inexact->exact
可以导致大的有理数(在这种意义上你分配了一对两个大整数) - 最好避免这种情况,
这样做仍然无法解决您所做的额外测试 - 但这只是因为您不确定您是否拥有正确的数字,如果您错过了1.鉴于它应该是关闭到一个整数,你可以使用round
然后进行一次检查,为你节省一次测试。
修复上述内容,并在一个函数中执行它,在找到它时返回数字,并使用一些更“明显”的标识符名称,我得到:
(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 :(得分:0)
当涉及精确取幂时,不同的方案表现不同:一些在可能的情况下返回一个精确的结果,一些在所有情况下都是不精确的结果。您可以查看我ExactExpt页面中的一个implementation contrasts,了解哪些方案可以执行哪些操作。