简体   繁体   中英

Addition of Binary Numbers in Haskell

I need to create a function to add a binary number to another one. It's a task for my study and I'm not that much into Haskell and could use some help.

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.

..so for example Odd(Even(Odd Zero))) is equal to 101... and that is my function so far.

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.

In that case, more descriptive names for Odd and Even could be Twice and TwicePlus1 .

Mapping B objects to Integers:

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:

plusB :: B -> B -> B

we have 3*3 = 9 equations to write. But 5 of them involves Zero which is the neutral element, and so are quite easy to write:

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) .

Thinking of Odd and Even as TwicePlus1 and Twice respectively:

(Odd a) + (Odd b) ≃ (2 a+1)+(2 b+1) = 2 + 2*(a+b) ≃ Even (Odd Zero) + Even (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)

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)

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 , this representation has the nice advantage of requiring only O(log(n)) nested constructors, instead of O(n).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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