简体   繁体   English

Haskell 中的二进制数相加

[英]Addition of Binary Numbers in Haskell

I need to create a function to add a binary number to another one.我需要创建一个 function 将二进制数添加到另一个二进制数。 It's a task for my study and I'm not that much into Haskell and could use some help.这是我的学习任务,我不太喜欢 Haskell 并且可以使用一些帮助。

I already made the datatype which I have to use.我已经制作了我必须使用的数据类型。

data B = Zero
    | Even B
    | Odd B
    deriving (Show, Generic)
instance Listable B where tiers = genericTiers

Even means 0, Odd means 1 and Zero is the end. Even表示 0, Odd表示 1, Zero表示结束。

..so for example Odd(Even(Odd Zero))) is equal to 101... and that is my function so far. ..所以例如 Odd(Even(Odd Zero))) 等于 101 ......到目前为止,这就是我的 function。

plusB :: B -> B -> B
plusB (Odd a) (Odd b) = Odd (Even (plusB a b))
plusB (Even a) (Even b) =  Even (plusB a b)
plusB (Even a) (Odd b) = Odd (plusB a b)
plusB (Odd a) (Even b) = Odd (plusB a b)
plusB (Zero) (Zero) = .....

I think that I have to use recursion for it to work.我认为我必须使用递归才能工作。

I hope that makes sense.我希望这是有道理的。

If you assume that the Even constructor returns the image of an even number, and that the Odd constructor returns the image of an odd number, this implies that the outermost constructor maps to the rightmost (least significant) bit.如果假设Even构造函数返回偶数的图像,而Odd构造函数返回奇数的图像,这意味着最外面的构造函数映射到最右边(最低有效位)位。

In that case, more descriptive names for Odd and Even could be Twice and TwicePlus1 .在这种情况下,对OddEven更具描述性的名称可能是TwiceTwicePlus1

Mapping B objects to Integers:将 B 对象映射到整数:

toIntegerFromB :: B -> Integer
toIntegerFromB  Zero    =  0
toIntegerFromB (Even x) =  2*(toIntegerFromB x)
toIntegerFromB (Odd x)  =  1 + 2*(toIntegerFromB x)

As for the addition of two B objects:至于添加两个B对象:

plusB :: B -> B -> B

we have 3*3 = 9 equations to write.我们有 3*3 = 9 个方程要写。 But 5 of them involves Zero which is the neutral element, and so are quite easy to write:但其中有 5 个涉及中性元素Zero ,因此很容易编写:

plusB  (Zero)    (Zero)     =  Zero
plusB  (Zero)    (Even a)   =  Even a
plusB  (Even a)  (Zero)     =  Even a
plusB  (Zero)    (Odd a)    =  Odd a
plusB  (Odd a)   (Zero)     =  Odd a

Regarding the 4 remaining equations, we note that number 1 maps to Odd Zero and that number 2 maps to Even (Odd Zero) .关于剩下的 4 个等式,我们注意到数字 1 映射到Odd Zero ,而数字 2 映射到Even (Odd Zero)

Thinking of Odd and Even as TwicePlus1 and Twice respectively:OddEven分别视为TwicePlus1Twice

(Odd a) + (Odd b) ≃ (2 a+1)+(2 b+1) = 2 + 2*(a+b) ≃ Even (Odd Zero) + Even (a+b) (奇数 a) + (奇数 b) ≃ (2 a+1)+(2 b+1) = 2 + 2*(a+b) ≃ 偶数 (奇零) + 偶数 (a+b)

Hence the equation:因此等式:

plusB  (Odd a)   (Odd b)    =  plusB  (Even (Odd Zero))  (Even (plusB a b))

Next, we have:接下来,我们有:

(Odd a) + (Even b) ≃ (2 a + 1) + (2 b) = 1 + 2*(a+b) ≃ Odd (a+b) (奇数 a) + (偶数 b) ≃ (2 a + 1) + (2 b) = 1 + 2*(a+b) ≃ 奇数 (a+b)

Hence, using symmetry, the 2 equations:因此,使用对称性,两个方程:

plusB  (Even a)  (Odd b)    =  Odd  (plusB a b)
plusB  (Odd a)   (Even b)   =  Odd  (plusB a b)

The last remaining equation is easier:最后剩下的等式更简单:

(Even a) + (Even b) ≃ (2 a)+(2 b) = 2*(a+b) ≃ Even (a+b) (偶数 a) + (偶数 b) ≃ (2 a)+(2 b) = 2*(a+b) ≃ 偶数 (a+b)

plusB  (Even a)  (Even b)   =  Even (plusB a b)

Putting it all together:把它们放在一起:

plusB :: B -> B -> B
plusB  (Zero)    (Zero)     =  Zero
plusB  (Zero)    (Even a)   =  Even a
plusB  (Even a)  (Zero)     =  Even a
plusB  (Zero)    (Odd a)    =  Odd a
plusB  (Odd a)   (Zero)     =  Odd a
plusB  (Odd a)   (Odd b)    =  plusB  (Even (Odd Zero))  (Even (plusB a b))
plusB  (Even a)  (Even b)   =  Even (plusB a b)
plusB  (Even a)  (Odd b)    =  Odd  (plusB a b)
plusB  (Odd a)   (Even b)   =  Odd  (plusB a b)

Compared to the more common data Nat = Zero | Succ Nat与更常见的data Nat = Zero | Succ Nat data Nat = Zero | Succ Nat , this representation has the nice advantage of requiring only O(log(n)) nested constructors, instead of O(n). data Nat = Zero | Succ Nat ,这种表示的优点是只需要 O(log(n)) 嵌套构造函数,而不是 O(n)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM