在haskell中添加两个8位数字

时间:2013-07-11 16:41:56

标签: haskell

我试图定义一个函数,帮助我模拟使用8位数时的基本操作。

我很难搞清楚这一点。我试图保持尽可能简单而不导入任何内容,所以我开始使用两个包含8个元素的列表(它们是0& #39; s和1' s。

如果我没弄错,它应该从这样开始:

bitsum :: [Int] -> [Int] -> [Int]
bitsum [][] = []
在最后一行之后,它开始变得棘手,因为我无法将列表中的元素添加到一个。

bitsum (x:xs)(y:ys) 

我现在所拥有的一切,我认为是正确的。

我的想法是尝试这样的事情:

bitsum :: [Int] -> [Int] -> [Int]
bitsum [][] = []
bitsum (x:xs)[] = (x:xs)
bitsum [](y:ys) = (y:ys)
bitsum (x:xs)(y:ys) | (x:xs) == (y:ys) && < 0 = (x:xs)
                    | (x:xs) == (y:ys) && > 0 = 

但是我觉得我在某个地方转了个弯。

如果有人能帮我解决这个问题,我真的很感激。

3 个答案:

答案 0 :(得分:2)

你需要一个进位。您无法逐列添加。让我们一块一块地做:

bitsum :: [Int] -> [Int] -> [Int]
bitsum = bitsum' 0
  where
    bitsum' _ [] [] = []

这是一个开始。我们从没有进位开始,我们处理不再需要添加的位的情况。那么如果两个位都为0会怎么样?

    bitsum' 0 (0:xs) (0:ys) = 0 : bitsum' 0 xs ys
    bitsum' 1 (0:xs) (0:ys) = 1 : bitsum' 0 xs ys

好的,所以如果两者都是0,并且进位是0,那么该位的结果是0并且没有进位。如果有携带使用它,并继续没有。

    bitsum' 0 (1:xs) (1:ys) = 0 : bitsum' 1 xs ys
    bitsum' 1 (1:xs) (1:ys) = 1 : bitsum' 1 xs ys

如果他们是一个,那就相似了。除了总会有一个随身携带。然后,如果他们不同:

    bitsum' 0 (x:xs) (y:ys) = 1 : bitsum' 0 xs ys
    bitsum' 1 (x:xs) (y:ys) = 0 : bitsum' 1 xs ys

他们必须是0和1,因为我们处理了所有其他情况,因此他们必须加起来一个。你可以弄清楚它应该是什么。你开始看到上面的一些模式,所以这一切都可以缩小,最终得到更短的答案。

bitsum :: [Int] -> [Int] -> [Int]
bitsum = bitsum' 0
  where
    bitsum' _ [] [] = []
    bitsum' carry (x:xs) (y:ys) | x == y = carry : bitsum' x xs ys
                                | otherwise = (1 - carry) : bitsum' carry xs ys

(1-carry)是一种翻转1到0的奇特方式,反之亦然,因为在这种情况下,该位总是与进位相反。

答案 1 :(得分:2)

这是不必要的。注意按位二进制加法的两个属性:高位由AND给出,低位由XOR给出。这些是:

xor a b = if a == b then 0 else 1

and' 1 1 = 1 -- `and` is a function in Prelude.
and' _ _ = 0

要找到二进制和,只需按位xor和和分别找到低位和高位。移动高位数(左或右,取决于Endian-ness)并取总和,以及低位数。

Little endian:

bitsum0 :: [Int] -> [Int] -> [Int]
bitsum0 xs ys
    | (sum xs) == 0 = ys
    | (sum ys) == 0 = xs
    | otherwise = bitsum0 low (0:high)
        where low = zipWith xor xs ys
              high = zipWith and' xs ys

Big endian:

bitsum1 :: [Int] -> [Int] -> [Int]
bitsum1 xs ys
    | (sum xs) == 0 = ys
    | (sum ys) == 0 = xs
    | otherwise = bitsum1 low ((tail high) ++ [0])
        where low = zipWith xor xs ys
              high = zipWith and' xs ys

每个功能中的两名警卫确保终止;最终,递归将最终添加x + 0,这是我们完成的时候。

请注意,没有进行错误检查。溢出和不同长度的列表(以及空列表)是未定义的行为。你的列表可能被填满无意义的垃圾(特别是,and'将0视为0,其他一切视为1)。也许使用像

这样的东西会更实用
data Bit = Bool
type Word_8 = (Bit , Bit , Bit , Bit , Bit , Bit , Bit , Bit )

或更好

import Data.Word
binsum :: Word8 -> Word8 -> Word8
binsum = (+)

答案 2 :(得分:0)

这是Haskell中的一个超级简单的门表示。 刚开始学习Haskell,所以格式很简单,我学习的方式...... 由于在数学中建立一点模拟似乎很有趣,我一起攻击这个..希望它能帮助某人:)

andGate x y = [z | z <- [if (x == 1 && y == 1) then 1 else 0]]

orGate x y = [z | z <- [if (x == 1 || y == 1) then 1 else 0]]

nandGate x y = [z | q <- (andGate x y), z <- [if (q == 0) then 1 else 0 ]]

norGate x y  = [z | q <- (orGate x y), z <- [if (q == 0) then 1 else 0 ]]

xorGate x y  = [z | 
 xn <- [if (x == 0) then 1 else 0], 
 yn <- [if (y == 0) then 1 else 0],
 q  <- (andGate xn y), 
 p  <- (andGate x yn), 
 z  <- (orGate q p)]

xnorGate x y  = [z | 
 xn <- [if (x == 0) then 1 else 0], 
 yn <- [if (y == 0) then 1 else 0],
 q  <- (andGate xn yn), 
 p  <- (andGate x y), 
 z  <- (orGate q p)]

halfAdder a b = [ (x, y) | x <- (xorGate a b), y <- (andGate a b)]

fullAdder a b c = [ (sum, cout) |
 u1     <- xorGate a b,
 u2     <- andGate a b,
 sum    <- xorGate u1 c,
 u4     <- andGate u1 c,
 cout   <- orGate u4 u2]