Horner's algorithm in SML? [closed]

▼魔方 西西 提交于 2019-12-02 23:52:48

问题


I am trying to implement Horner's algorithm in SML.

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;

Takes on a{n}, the coeff of x^n, as its initial result, then using horner's evaluates a polynomial.

Evaluates as ((a{n}*x+a{n-1})*x+a{n-2})..The list contains the coefficients of the polynomial. Problem is the "if lst1 = []....else" part. Employing only the while loop makes the program run well. But I can't think of anything that is wrong with that part.


回答1:


You've tried to write some very imperative-looking code, and frankly, it's a bit of a mess. If you try to write your SML code as if it was Java, well, that's gonna hurt.

Instead of trying to fix your original code, let's redo it in a more functional style. First of all, pattern matching. In your code, you use an if-then-else expression to check if your list is empty. Instead, we'll use pattern matching:

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

This has two benefits. First, it splits the list up for us - we can now use n to refer to the first item in the list, and ns to refer to the rest. Second, it's way more readable.

Now we need the actual math. Now, horner's method uses a variable, which you've called result in your code, to accumulate the answer. However, we're coding in a mostly functional language, and avoiding refs would be nice. Instead, we'll add an extra parameter to the function.

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

Of course, we want the function to be usable with only two parameters, so we put the math in a helper function, and make the real function call the helper function:

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

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

This is a fairly common pattern to see in functional programming, and SML has tools to hide the helper function so we don't clutter up the global namespace. For example, we could put the helper function inside a let-expression:

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

Finally, we add the recursive call of 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

And here's an of what happens when we call the horner function:

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


来源:https://stackoverflow.com/questions/25099601/horners-algorithm-in-sml

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!