【问题标题】:SML: Implementing Multiply with RestrictionsSML:使用限制实现乘法
【发布时间】:2015-11-08 17:59:56
【问题描述】:

我正在尝试在 SML 中实现乘法,但有一些限制。我得到了以下add 函数:

fun add (0 : int, m : int) : int = m
    | add (n : int, m : int) : int = 1 + add(n-1, m)

我正在尝试编写一个函数,以便 mult (m, n) 递归地计算 m 和 n 的乘积,对于任意两个自然数 mn。你的实现可以使用上面提到的函数add-(减法),但不能使用+*

这是我的尝试:

fun multiply(0 : int, m : int) = 0
    | multiply(n : int, 0 : int) = 0
    | multiply(1 : int, m : int) = m
    | multiply(n : int, 1 : int) = n
    | multiply(~1 : int, m : int) = ~m
    | multiply(n : int, ~1 : int) = ~n
    | multiply(n : int, m : int) =
        if (n > 0 andalso m > 0) then
            add(add(0, n), multiply(n, m - 1))
        else
            if (n < 0 andalso m < 0) then
                multiply(~n, ~m)
            else
                if (n < 0 andalso m > 0) then
                    n - multiply(n, m - 1)
                (* n > 0 and m < 0 *)
                else
                    m - multiply(m, n - 1);

nm 都为正数或均为负数时有效,但当一个为正数另一个为负数时无效,但我似乎无法找出我的错误。例如,

multiply(3, ~10) 计算结果为 0。所以我认为我的递归调用正在到达0 并导致它评估为0。话虽如此,我的基本案例已经解决了这个问题,所以我不确定这怎么可能。

想法?

【问题讨论】:

  • 也许将m - multiply(m, n - 1); 更改为m - multiply( n - 1,m);?递归可能搞砸了?接触 SML 已经 4 年了,抱歉我不能更有用了
  • @Parker 你为什么这么建议? (不是说错了,但也对你的推理感兴趣)
  • 快速浏览一下,您似乎正在根据正负两个值来处理事情,如果您不断递归并且 n 和 m 不断变化点,则可能会弄乱逻辑。就像函数总是期望 (n,m) 一样,但您传递的是 (m,n)。同样,我可能忘记了 SML 函数
  • 为什么 n 和 m 一直在换位置?
  • 啊,我明白你在说什么。是的,我无意中翻转了它们,尽管我在调用 multiply(~3, 10) 时仍然遇到同样的问题,呵呵

标签: recursion functional-programming sml smlnj


【解决方案1】:

m - multiply(m, n - 1); 更改为m - multiply(~m, n - 1);。 (对于其他 n -... 行也是如此)您拥有它的方式是从自身中减去一个负数,因此您实际上是在将其抵消,并触发 0 的基本情况。

追踪:

= multiply (3, -10)
= -10 - multiply (2, -10)
= -10 - (-10) - multiply (1, -10)
= -10 - (-10) - (-10)

只要有 (-10) - (-10),你就会触发 multiply(0 : int, m : int),这会导致 0,所以你对它被触发的直觉是正确的。

我意识到你不能使用+,所以下面是代码。因为您需要乘法,所以我们保持基本逻辑相同,但不是使用相同的数字进行递归,而是在将负数传递给递归调用之前将其转为正数。

fun multiply(0 : int, m : int) = 0
    | multiply(n : int, 0 : int) = 0
    | multiply(1 : int, m : int) = m
    | multiply(n : int, 1 : int) = n
    | multiply(~1 : int, m : int) = ~m
    | multiply(n : int, ~1 : int) = ~n
    | multiply(n : int, m : int) =
        if (n > 0 andalso m > 0) then
            add(add(0, n), multiply(n, m - 1))
        else if (n < 0 andalso m < 0) then
            multiply(~n, ~m)
        else if (n < 0 andalso m > 0) then
            n - multiply(~n, m - 1)
        else  (* n > 0 and m < 0 *)
            m - multiply(n - 1, ~m);

还有一个小问题,但您可以将 add(add(0, n), multiply(n, m - 1)) 更改为 add(n, multiply(n, m - 1))

【讨论】:

  • 吹毛求疵 :)
猜你喜欢
  • 2013-01-11
  • 1970-01-01
  • 1970-01-01
  • 2012-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多