1

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

我很难弄清楚这一点。我试图在不导入任何内容的情况下使其尽可能简单,因此我从其中包含 8 个元素的两个列表开始(分别是 0 和 1)。

如果我没记错的话,它应该开始看起来像这样:

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 = 

但我想我在某个地方走错了路。

如果有人能帮我解决这个问题,我将不胜感激。

4

3 回答 3

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,因为我们已经处理了所有其他情况,所以它们必须加起来为 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 的奇特方式,反之亦然,因为在这种情况下,位总是与进位相反。

于 2013-07-12T01:11:40.080 回答
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

要找到二进制和,只需按位异或,并分别找到低位和高位。移动高位(左或右,取决于字节序)并取其和低位。

小端:

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

大端:

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 = (+)
于 2013-07-13T02:40:49.507 回答
0

这是 Haskell 中一个超级简单的门表示。刚开始学习 Haskell,所以格式很简单,我的学习方式也很简单。因为在数学中构建一点 sim 看起来很有趣,所以我一起破解了这个。希望对某人有所帮助:)

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]
于 2016-12-07T13:13:50.463 回答