两个补码尽可能简单,没有高阶函数

时间:2015-11-09 02:22:21

标签: haskell twos-complement

对于作业,我被要求在Haskell中实现二进制补码方法,当给出Binary中的数字列表时,返回该列表的两个补码列表。

>>>twoComplement [0,0,0,1,1,0,1,0]
[1,1,1,0,0,1,1,0]

因此我不允许使用更高阶的函数,例如lastinit等。这必须尽可能简单。我想学习编写漂亮的代码。

我想在不使用反向函数的情况下这样做,但如果需要,我可以允许。

我已经尝试了很多东西。我知道我需要翻转所有的位,这并不复杂。

flipBits [] = []
flipBits (x:xs)
         |x == 0 = 1:flipBits xs
         |x == 1 = 0:flipBits xs
         |otherwise: error "Only 0 and 1 are allowed."

但添加一部分对我来说感觉非常复杂。特别是如果我向已经存在的1添加1,则继续进行。也不允许列表生成器。这是关于理解列表和连接符:的全部内容。

编辑:在vkuo的帮助下,我写了以下内容,到目前为止,这似乎做得很好。

twoComplement:: [Integer] -> [Integer]
twoComplement [] = []
twoComplement lst = turn(tC(turn(lst)))
                where
                    tC (x:xs)
                        |x == 1 = 1:flipp xs
                        |x == 0 = x:tC xs
                    flipp [] = []
                    flipp(x:xs)
                        |x == 0 = 1:flipp xs
                        |x == 1 = 0:flipp xs
                    turn [] = []
                    turn (x:xs) = turn xs ++ [x]

如果我们想使用reverse,我们必须自己制作。所以我做到了。我不知道有没有反向的方法吗?

1 个答案:

答案 0 :(得分:1)

如果您不想反转,那么您可以随时看到一个原始数字和列表其余部分的结果。余数的结果是二进制补码加进位数。你必须返回相同类型的结果,即一个进位数加上一个二进制补码,尽管还要考虑一个数字。

这样的事情:

  std::vector<std::vector<float> * > v(matrix_count);   
  for(int i=0; i < matrix_count; i++) {
    v[i] = new std::vector<float>(array_size);
  }

  for(int i=0; i < matrix_count; i++) {
    std::ifstream is(files[i]);
    is.read((char*) &((*v[i])[0]), size);
    is.close();
  }

现在如果你只有一位数,那么整个操作将是:

invAdd :: Int -> (Int,[Int]) -> (Int,[Int])
invAdd 0 (0,ds) = (0,1:ds)
invAdd 0 (1,ds) = (1,0:ds)
invAdd 1 (0,ds) = (0,0:ds)
invAdd 1 (1,ds) = (0,1:ds)

twos :: [Int] -> (Int,[Int]) twos (d:[]) = invAdd d (1,[]) 满足(1,[])您需要添加的内容来翻转位。

如果您有多个数字,则需要递减

1

这为您提供了两个补码加上最后一个进位。如果您不想查看随身携带,请使用twos (d:ds) = invAdd d (twos ds)

snd

您也可以使用Bools轻松完成此操作,因为没有使用数学函数,并且在*Main> snd (twos [0,0,0,1,1,0,1,0]) [1,1,1,0,0,1,1,0] 中明确说明了所有情况。