【发布时间】:2018-06-10 20:43:50
【问题描述】:
**这是一种用相当古老的语言标准 ML 实现的算法。我很难理解这个算法:
fun polyquotremd ts ((n,b) :: us) =
let fun quo [] qs = (rev qs, [])
| quo ((m,a) :: ts) qs =
if m < n then (rev qs, (m,a) :: ts)
else
quo (polysum ts
(map (termproduct(m-n, ~a/b)) us))
((m-n, a/b) :: qs)
in
quo ts []
end;
这是目标。我们通过使用元组列表密集地表示多项式,每个元组包含索引 0 处的幂和索引 1 处的系数。例如,$x^2 + 1$ 表示为[(2, 1.0), (0, 1.0)]。这是由 (int*real)list 类型给出的,如下面的辅助函数所示。我们想要得到一个输出(quo, rem),每个都是一个元组列表,分别表示商和余数。 ts 是要被除的多项式,而 us 是除数。
这是我想象的算法的工作原理:
首先,如果
ts = []意味着我们没有多项式可除,所以我们返回 qs,我们的累积商结果作为答案。由于我们不断将((m-n, a/b) :: qs)添加到 qs 列表的头部,因此我们需要反转列表以使列表以最大指数开始。第一个 if 条件处理除数的指数 n 大于我们正在处理的当前幂 m 的情况。在这种情况下,我们只是不添加元素并返回
(rev qs, (m,a) :: ts),即(quo, rem)else 条件是我混淆的部分。我知道第二个括号
((m-n, a/b) :: qs)是我们要添加的累积结果,但是polysum ts (map (termproduct(m-n, ~a/b)) us))实际上在做什么呢?这背后的数学原理是什么?
通常,我们会一次将多项式除数相除,即 $x+1$ 一起。但是这个算法首先使用 $x$,然后是 $1$。这甚至是如何工作的?为什么会有~a/b(供您参考,意思是-a/b)。
辅助函数:
fun take ([], _) = []
| take (x::xs, i) = if i>0
then x :: take(xs, i-1)
else [];
fun drop ([], _) = []
| drop (x::xs, i) = if i>0 then drop(xs,i-1)
else x::xs;
fun termproduct (m,a) (n,b) = (m+n, a*b) : (int*real);
fun polyproduct [] us = []
| polyproduct [(m,a)] us = map (termproduct(m,a)) us
| polyproduct ts us =
let
val k = length ts div 2
in
polysum (polyproduct (take(ts,k)) us)
(polyproduct (drop(ts,k)) us)
end;
有人可以向我解释第 3 点吗?我对此感到非常困惑,尤其是这个算法的数学。但它有效.. 仅供参考,此代码可以编译,您可以在标准 ML 中对其进行测试。
【问题讨论】:
-
(添加了 Haskell 标签,因为很多聪明人,他们使用非常相似的语言,检查一下 :)
-
标签不是为了“让更多人看到问题”。他们是为了“这个问题是关于这个标签所代表的实体”。
-
@JoshCaswell 如果我想让“更多”人看到这个问题,我会添加“javascript”标签:) 相反,函数声明看起来类似于 Haskell 代码,我知道许多喜欢数学的程序员都喜欢。
-
@JoshCaswell 作为原则,我也不同意你的观点。理性的人可能对标签是否完全适合有不同的看法。吸引那些可能对密切相关的类别感兴趣的人的注意力似乎完全可以接受。我的意思是 OP 是来回答问题的,对吧?不要为迂腐的编程百科全书项目服务。
-
“古风”?与目前主流的语言相比,它具有未来感。
标签: algorithm math functional-programming sml