Horner在SML中的算法?

时间:2014-08-02 21:31:57

标签: algorithm sml smlnj

我正在尝试在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;

接受{n},x ^ n的系数作为其初始结果,然后使用horner评估多项式。

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

1 个答案:

答案 0 :(得分:3)

你已经尝试过编写一些非常具有命令性的代码,坦率地说,这有点乱。如果你试图将你的SML代码编写为Java,那么,这会受到伤害。

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

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

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

现在我们需要实际的数学。现在,horner的方法使用一个变量,你在代码中调用了result来积累答案。但是,我们使用的函数主要是函数式语言,避免ref s会很好。相反,我们将在函数中添加一个额外的参数。

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