打印列表中最大数字长度时出现SML错误

时间:2015-02-23 04:03:37

标签: list recursion functional-programming sml

我使用3个函数查找列表中的最大数字并打印它的长度。

样本输入为maxL [5,199,3000,63];

fun max(a,b) = 
if 
    a>b 
then 
    a 
else 
    b;
fun maxL(L) = 
    if L=[] then 
        0
    else
        let 
            val largest = max(hd(L), maxL(tl(L)))
        in
            num_digits largest
        end;

fun num_digits 0 = 0
|num_digits 1 = 1
| num_digits x = num_digits(x div 10) + 1;

示例输入/输出

- maxL [5, 199, 3000, 63];
val it = 1 : int

在这里,我将程序修改为只打印最大,以验证它是否找到了最大的

- use "hw4.sml";
[opening hw4.sml]
val num_digits = fn : int -> int
val max_digits = fn : int list -> int
val max = fn : int * int -> int
val maxL = fn : int list -> int
val it = () : unit
- maxL [5, 199, 3000, 63];
val it = 3000 : int

在这里,我测试的是3000或者最大的,实际上正在打印出正确的长度。

- num_digits 3000;
val it = 4 : int

我的问题是:为什么我打电话给num_digits largest时打印1,但如果我打电话给num_digits 3000打印4?

3 个答案:

答案 0 :(得分:1)

maxL返回多个数字,但其返回值用作max的第二个参数,将该值与列表头部的值进行比较。由于列表中的数字不超过4位数,因此值为5,并且有1位数。因此输出。

答案 1 :(得分:1)

尝试手动减少表达式:

   maxL [5, 199, 3000, 63];
=> num_digits (max (5, maxL [199, 3000, 63]))
=> num_digits (max (5, num_digits (max (199, maxL [3000, 63]))))
=> num_digits (max (5, num_digits (max (199, num_digits (max (3000, maxL [63]))))))
=> num_digits (max (5, num_digits (max (199, num_digits (max (3000, num_digits (max (63, maxL []))))))))
=> num_digits (max (5, num_digits (max (199, num_digits (max (3000, num_digits (max (63, 0))))))))
=> num_digits (max (5, num_digits (max (199, num_digits (max (3000, num_digits 63))))))
=> num_digits (max (5, num_digits (max (199, num_digits (max (3000, 2))))))
=> num_digits (max (5, num_digits (max (199, num_digits 3000))))
=> num_digits (max (5, num_digits (max (199, 4))))
=> num_digits (max (5, num_digits 199))
=> num_digits (max (5, 3))
=> num_digits 5
   1

简而言之,maxL正在计算数字的位数,而不是数字列表中最大数,因此您可以&#39 ; t确实使用maxL生成的结果作为max的参数。

答案 2 :(得分:0)

  

我正在使用3个函数来查找列表中的最大数字并打印其长度。

以更简单的步骤分解您的目标:

  • 在列表中找到最大的数字
  • 并打印其长度

您可能已经看到这不是您正在做的事情。您的算法执行以下操作:

  • 分解第一个元素和尾部列表中的列表
  • 获得所述第一个元素与maxL(tail)
  • 之间的最大值
  • 计算该最大值的数字长度

如果将内部呼叫扩展为maxL,则差异变得明显:

  • 分解第一个元素和尾部列表中的列表
  • 分解第二个元素和第二个尾部列表中的尾部列表
  • 获取所述第二个元素与maxL(second tail)
  • 之间的最大值
  • 计算第一个最大值的数字长度
  • 获取所述第一个元素与之前最大
  • 数字长度之间的最大值
  • 计算该最大值的数字长度

为了修复算法,您需要将调用从num_digits拉出递归,然后按原定的目标应用它。