【问题标题】:Horner's algorithm in SML? [closed]SML 中的霍纳算法? [关闭]
【发布时间】:2014-09-25 19:12:53
【问题描述】:

我正在尝试在 SML 中实现 Horner's algorithm

fun horner(lst1:real list,x:real) = 
  let
    val i = ref 1
    val result = ref (List.last(lst1))
    in
      if (lst1) = ([]:real list) then 0.0 
      else
        while (!i <= length(lst1)-1) do
          (result:=!result*x+List.nth(lst1,length(lst1)-(!i)-1);
          i := !i+1);
          !result
      end;

将 x^n 的系数 a{n} 作为初始结果,然后使用 horner 计算多项式。

计算为 ((a{n}*x+a{n-1})*x+a{n-2})..列表包含多项式的系数。 问题是“if lst1 = []....else”部分。 仅使用 while 循环可使程序运行良好。 但我想不出这部分有什么问题。

【问题讨论】:

  • 你必须告诉我们问题出在哪里……代码应该做什么?它实际上是做什么的?
  • 你的代码目标是什么?
  • 我编辑了细节。
  • 每个输入的作用是什么?

标签: algorithm sml smlnj


【解决方案1】:

您尝试编写一些看起来非常命令式的代码,坦率地说,这有点混乱。如果您尝试像编写 Java 一样编写 SML 代码,那会很痛苦。

与其尝试修复您的原始代码,不如让我们以更实用的方式重做它。首先,模式匹配。在您的代码中,您使用if-then-else 表达式来检查您的列表是否为空。相反,我们将使用模式匹配:

fun horner ([]   , x) = 0.0
  | horner (n::ns, x) = ...

这有两个好处。首先,它为我们拆分列表——我们现在可以使用n 来引用列表中的第一项,并使用ns 来引用其余部分。其次,它更具可读性。

现在我们需要实际的数学运算。现在,horner 的方法使用您在代码中称为result 的变量来累积答案。但是,我们主要使用函数式语言进行编码,避免使用refs 会很好。相反,我们将向函数添加一个额外的参数。

fun horner ([]   , x, acc) = acc
  | horner (n::ns, x, acc) = ...

当然,我们希望函数只需要两个参数,所以我们把数学放在辅助函数中,让真正的函数调用辅助函数:

fun horner' ([]   , x, acc) = acc
  | horner' (n::ns, x, acc) = ...

fun horner (xs, x) = horner' (xs, x, 0.0)

这是在函数式编程中相当常见的模式,SML 具有隐藏辅助函数的工具,因此我们不会弄乱全局命名空间。例如,我们可以将辅助函数放在let-表达式中:

fun horner (xs, x) = let
                       fun horner' ([]   , x, acc) = acc
                         | horner' (n::ns, x, acc) = ...
                     in
                       horner' (xs, x, 0.0)
                     end

最后,我们添加horner'的递归调用。

fun horner (xs, x) = let
                       fun horner' ([]   , x, acc) = acc
                         | horner' (n::ns, x, acc) = horner' (ns, x, n + x * acc)
                     in
                       horner' (xs, x, 0.0)
                     end

下面是我们调用 horner 函数时发生的情况:

horner ([3.0, 2.0, 4.0], 2.0) ~> horner' ([3.0, 2.0, 4.0], 2.0, 0.0)
                              ~> horner' ([2.0, 4.0]     , 2.0, 3.0 + 2.0 * 0.0)
                              ~> horner' ([2.0, 4.0]     , 2.0, 3.0)
                              ~> horner' ([4.0]          , 2.0, 2.0 + 2.0 * 3.0)
                              ~> horner' ([4.0]          , 2.0, 8.0)
                              ~> horner' ([]             , 2.0, 4.0 + 2.0 * 8.0)
                              ~> horner' ([]             , 2.0, 20.0)
                              ~> 20.0

【讨论】:

  • 非常感谢!所以你的意思是在 sml 中使用循环是不可取的?
  • 是的。好吧,我的意思是,它是语言的一部分并且可以使用,但在大多数情况下,递归将在更少的行中完成这项工作,并且更少令人头疼。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
  • 1970-01-01
  • 1970-01-01
  • 2011-04-11
  • 2015-03-30
  • 1970-01-01
相关资源
最近更新 更多