- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试实现一个实现n 个立方体之和的函数:
1^3 + 2^3 + 3^3 + ... + n^3 = sum
我的函数应该接收一个 sum
并返回一个 n
或 -1
(如果 n
不存在) .
一些例子:
(find-n 9) ; should return 2 because 1^3 + 2^3 = 9
(find-n 100) ; should return 4 because 1^3 + 2^3 + 3^3 + 4^3 = 100
(find-n 10) ; should return -1
经过一些工作,我制作了这两个函数:
; aux function
(defn exp-3 [base] (apply *' (take 3 (repeat base))))
; main function
(defn find-n [m]
(loop [sum 0
actual-base 0]
(if (= sum m)
actual-base
(if (> sum m)
-1
(recur (+' sum (exp-3 (inc actual-base))) (inc actual-base))))))
这些函数工作正常,但使用 BigNumbers
评估操作花费的时间太长,例如:
(def sum 1025247423603083074023000250000N)
(time (find-n sum))
; => "Elapsed time: 42655.138544 msecs"
; => 45001000
我问这个问题是为了提出一些关于如何使这个功能更快的建议。
最佳答案
这都是关于代数的,与 Clojure 或编程无关。由于这个网站不支持数学排版,所以我们用 Clojure 来表达它。
定义
(defn sigma [coll] (reduce + coll))
和
(defn sigma-1-to-n [f n]
(sigma (map f (rest (range (inc n))))))
(或
(defn sigma-1-to-n [f n]
(->> n inc range rest (map f) sigma))
)
那么问题是,给定 n
,找到 i
使得 (= (sigma-1-to-n #(* % % %) i) n)
。
快速完成此操作的关键是 Faulhaber's formula对于立方体。它告诉我们,对于任何自然数 i
,以下内容都是相等的:
(#(*' % %) (sigma-1-to-n identity i))
(sigma-1-to-n #(* % % %) i)
(#(*' % %) (/ (*' i (inc i)) 2))
所以,作为立方之和,数字
为了确定一个整数是否是完全平方数,我们取其近似的浮点平方根,然后看看对最接近的整数进行平方是否可以恢复我们的整数:
(defn perfect-square-root [n]
(let [candidate (-> n double Math/sqrt Math/round)]
(when (= (*' candidate candidate) n)
candidate)))
如果参数不是完全平方数,则返回nil
。
现在我们有了平方根,我们必须确定它是否是一系列自然数的和:在普通代数中,是(j (j + 1))/2
,对于某个自然数j
。
我们可以使用类似的技巧来直接回答这个问题。
j (j + 1) = (j + 1/2)^2 + 1/4
因此,以下函数返回与参数相加的连续数字的数量(如果有):
(defn perfect-sum-of [n]
(let [j (-> n (*' 2)
(- 1/4)
double
Math/sqrt
(- 0.5)
Math/round)]
(when (= (/ (*' j (inc j)) 2) n)
j)))
我们可以结合这些来完成您想要的操作:
(defn find-n [big-i]
{:pre [(integer? big-i) ((complement neg?) big-i)]}
(let [sqrt (perfect-square-root big-i)]
(and sqrt (perfect-sum-of sqrt))))
(def sum 1025247423603083074023000250000N)
(time (find-n sum))
"Elapsed time: 0.043095 msecs"
=> 45001000
(请注意,时间比以前快了大约二十倍,可能是因为 HotSpot 必须在 find-n
上工作,该功能已通过附加测试进行了彻底的测试)
这显然比原来快很多。
<小时/>警告
由于浮点精度有限,我担心上述过程可能会产生误报(它永远不会产生误报)。然而,测试表明,对于问题所使用的数字类型,该过程是牢不可破的。
<小时/>Java double
具有 52 位精度,大约为 15.6 位小数。令人担忧的是,对于比这大得多的数字,该过程可能会错过精确的整数解,因为舍入只能与它开始的 float 一样准确。
但是,该过程可以正确求解 31 位整数的示例。并且用许多(一千万!)相似的数字进行测试不会产生任何失败。
<小时/>为了测试解决方案,我们生成一个(惰性)[limitcube-sum]
对序列:
(defn generator [limit cube-sum]
(iterate
(fn [[l cs]]
(let [l (inc l)
cs (+' cs (*' l l l))]
[limit cs]))
[limit cube-sum]))
例如,
(take 10 (generator 0 0))
=> ([0 0] [1 1] [2 9] [3 36] [4 100] [5 225] [6 441] [7 784] [8 1296] [9 2025])
现在我们
所以
(remove (fn [[l cs]] (= (find-n cs) l)) (take 10000000 (generator 45001000 1025247423603083074023000250000N)))
=> ()
它们都有效。没有失败。只是为了确保我们的测试有效:
(remove (fn [[l cs]] (= (find-n cs) l)) (take 10 (generator 45001001 1025247423603083074023000250000N)))
=>
([45001001 1025247423603083074023000250000N]
[45001002 1025247514734170359564546262008N]
[45001003 1025247605865263720376770289035N]
[45001004 1025247696996363156459942337099N]
[45001005 1025247788127468667814332412224N]
[45001006 1025247879258580254440210520440N]
[45001007 1025247970389697916337846667783N]
[45001008 1025248061520821653507510860295N]
[45001009 1025248152651951465949473104024N]
[45001010 1025248243783087353664003405024N])
一切都应该失败,他们也确实失败了。
关于optimization - 循环函数花费的时间太长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45180110/
我有一个如下所示的数据框: import pandas as pd d = {'decil': ['1. decil','1. decil','2. decil','2. decil','3. dec
我有一些数据想要添加到我的应用中...大约 650 个类别(包括名称 + ID 号),每个类别平均有 85 个项目(每个都有一个名称/ID 号)。 iPhone会支持这么大的plist吗?我想首先在
我目前正在使用 Python 从头开始实现决策树算法。我在实现树的分支时遇到了麻烦。在当前的实现中,我没有使用深度参数。 发生的情况是,要么分支结束得太快(如果我使用标志来防止无限递归),要么如果
我在 Stack 上发现了这个问题 - Measuring the distance between two coordinates in PHP 这个答案在很多方面似乎对我来说都是完美的,但我遇到了
我目前正在清理一个具有 2 个索引和 2.5 亿个事件行以及大约同样多(或更多)的死行的表。我从我的客户端计算机(笔记本电脑)向我的服务器发出命令 VACCUM FULL ANALYZE。在过去的 3
这一切都有点模糊,因为该计划是相当深入的,但坚持我,因为我会尽量解释它。我编写了一个程序,它接受一个.csv文件,并将其转换为MySQL数据库的INSERT INTO语句。例如: ID Numbe
我有一个地址示例:0x003533,它是一个字符串,但要使用它,我需要它是一个 LONG,但我不知道该怎么做:有人有解决方案吗? s 字符串:“0x003533”到长 0x003533 ?? 最佳答案
请保持友善 - 这是我的第一个问题。 =P 基本上作为一个暑期项目,我一直在研究 wikipedia page 上的数据结构列表。并尝试实现它们。上学期我参加了 C++ 类(class),发现它非常有
简单的问题。想知道长 IN 子句是否是一种代码味道?我真的不知道如何证明它。除了我认为的那样,我不知道为什么它会闻起来。 select name, code, capital, pop
我正在尝试基于 C# 中的种子生成一个数字。唯一的问题是种子太大而不能成为 int32。有什么方法可以像种子一样使用 long 吗? 是的,种子必须很长。 最佳答案 这是我移植的 Java.Util.
我一直想知道这个问题有一段时间了。在 CouchDB 中,我们有一些相当的日志 ID……例如: “000ab56cb24aef9b817ac98d55695c6a” 现在,如果我们正在搜索此项目并浏览
列的虚拟列 c和一个给定的值 x等于 1如果 c==x和 0 其他。通常,通过为列创建虚拟对象 c , 一排除一个值 x选择,因为最后一个虚拟列不添加任何信息 w.r.t.已经存在的虚拟列。 这是我如
使用 tarantool,为什么我要记录这些奇怪的消息: 2016-03-24 16:19:58.987 [5803] main/493623/http/XXX.XXX.XXX.XXX:57295 t
我显然是 GitHub 的新手,想确保在开始之前我做的事情是正确的。 我想创建一个新的存储库,它使用来自 2 个现有项目的复刻/克隆。现有项目不是我的。 假设我想使用的 repo 被称为来自开发人员“
我的应用程序名称长度为 17 个字符。当安装在设备上时,它看起来像应用程序...名称。有没有办法在多行上显示应用程序名称?请帮忙。 最佳答案 不,你不能。我认为 iPad 支持 15 个字符来完整显示
我必须编写一个程序来读取文件中的所有单词,并确定每个单词使用了多少次。我的任务是使用多线程来加快运行时间,但是单线程程序的运行速度比多线程程序快。我曾尝试研究此问题的解决方案,但很多解释只会让我更加困
假设我在给定的范围内有一个位置pos,这样: 0 = newRange*newRange : "Case not supported yet"; // Never happens in my code
我试图在 Java 中将 unix 时间四舍五入到该月的第一天,但没有成功。示例: 1314057600 (Tue, 23 Aug 2011 00:00:00 GMT) 至 1312156800
我们的项目有在 CVS 中从现有分支创建新分支的历史。几年后,这导致了每次发布时更改的文件上的这种情况: 新版本:1.145.4.11.2.20.2.6.2.20.2.1.2.11.2.3.2.4.4
我有以下数据框: DAYS7 <- c('Monday','Tuesday','Wednesday','Thursday','Friday', 'Saturday', 'Sunday') DAYS
我是一名优秀的程序员,十分优秀!