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

SML error in printing off length of largest number in a list

我正在使用 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;

样本input/output

- 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?

maxL 是 return 数位,但其 return 值用作 max 的第二个参数,将该值与列表头部的值进行比较。由于列表中没有数字超过 4 位,因此取 5 为准,它有 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计算的是数字的位数,而不是列表的最大数字的数字,所以你不能真正使用 maxL 产生的结果作为 max.

的参数

I'm using 3 functions to find the largest number in a list and print its length.

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

  • 找出列表中最大的数字
  • 并打印它的长度

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

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

如果将内部调用扩展到 maxL,区别就会变得很明显:

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

为了修复算法,您需要将对 num_digits 的调用从递归中拉出,然后按照您最初陈述的目标应用它。