【问题标题】:conversion from decimal to binary in SMLSML中十进制到二进制的转换
【发布时间】:2014-02-24 01:32:38
【问题描述】:

我有以下公式

fun foo 0 = [0] 
  | foo num = let val l =  (num mod 2)::foo(num div 2) in
           rev l
           end;

应该从十进制转换为二进制。它具有以下签名

val foo = fn : int -> int list

由于我得到不正确的结果,我不确定我到底在哪里弄错了。有人可以帮我弄清楚我在哪里出错了吗?

【问题讨论】:

    标签: sml smlnj


    【解决方案1】:

    问题似乎在于您在每个递归步骤中反转结果列表,而不是在最后一次。

    另外,你可能需要将 0 映射到空列表,否则最后你会有一个 0 太多。

    【讨论】:

    • 我终于明白了,我在所有转换后都反转了local fun convert 0 = [0] | convert x = if x = 1 then [1] else (Int.rem(x,2))::convert(x div 2) in fun foo num = rev (convert(num)) end;
    【解决方案2】:

    正是安德烈亚斯所说的。现在,解决这个问题的明显方法是使用包装函数:

    fun f n =
    let
      fun f' 0   = []
        | f' num = num mod 2 :: f' (num div 2)
    in
      rev (f' n)
    end
    

    这可行,但缺点是首先建立列表,然后遍历它(rev 调用)。它也不是尾递归的。我们可以做得更好!

    我们不使用反向,而是翻转并使用累加器:

    fun g n =
    let
      fun g' 0   acc = acc
        | g' num acc = g' (num div 2) (num mod 2 :: acc)
    in
      g' n []
    end
    

    要了解其中的区别,让我们看看如果我们在数字 4 上运行这些中的每一个会发生什么。

    f 4 -> rev (f' 4)
        -> rev (4 mod 2 :: f' (4 div 2))
        -> rev (0 :: f' 2)
        -> rev (0 :: 2 mod 2 :: f' (2 div 2))
        -> rev (0 :: 0 :: f' 1)
        -> rev (0 :: 0 :: 1 mod 2 :: f' (1 div 2))
        -> rev (0 :: 0 :: 1 :: f' 0)
        -> rev (0 :: 0 :: 1 :: [])
        -> [1, 0, 0]
    
    g 4 -> g' 4 []
        -> g' (4 div 2) (4 mod 2 :: [])
        -> g' 2 (0 :: [])
        -> g' (2 div 2) (2 mod 2 :: 0 :: [])
        -> g' 1 (0 :: 0 :: [])
        -> g' (1 div 2) (1 mod 2 :: 0 :: 0 :: [])
        -> g' 0 (1 :: 0 :: 0 :: [])
        -> [1, 0, 0]
    

    【讨论】:

      猜你喜欢
      • 2023-04-11
      • 2016-02-09
      • 2016-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多