Home > Blockchain >  Subtraction with carry of positive numbers
Subtraction with carry of positive numbers

Time:12-02

Given two lists of digits such as [1, 2, 0] = 120 and [1,0,1] = 101, my function sub should return the list [1, 9] = 19 but the function is returning [2, -1] instead. How do I solve this carry problem? It works fine when there isn't a carry and it only receives positive numbers. Here's the code I have:

sub_Carry :: Integer -> [Integer] -> [Integer] -> [Integer]
sub_Carry c x []
            | c == 0 = x
            | otherwise = sub_Carry 0 [c] x
sub_Carry c [] x
            | c == 0 = x
            | otherwise = sub_Carry 0 x [c]
sub_Carry c (x : xs) (y : ys) = (x - y) : sub_Carry c xs ys

sub :: [Integer] -> [Integer] -> [Integer]
sub op1 op2
       | to_Integer(op1) == to_Integer(op2) = [0]
       | to_Integer(op1) > to_Integer(op2) = drop_Zeros (reverse (sub_Carry 0 (reverse op1) (reverse op2)))
       | otherwise = [-1]    drop_Zeros (reverse (sub_Carry 0 (reverse op1) (reverse op2)))

Other considerations:

  • I've have other utility functions such as to_Integer that converts the list into it's correspondent integer, drop_Zeros that removes zeros to the right of the list ([0, 1, 0] = [1, 0])
  • in the case the result is a negative number it should return the list with -1 at the head ([1, 0, 0] - [1, 0, 1] = [-1, 1])

CodePudding user response:

I noticed that you don't use the parameter c for carrying. It is the central point of the exercise. It is also necessary to solve the case when the list of a parameter y ends earlier than x. My program works only for positive results. So I also modified the function sub to reverse parameters when op1 < op2. Now there should be always a positive result, which you then negate using the constant -1.

sub_Carry :: Integer -> [Integer] -> [Integer] -> [Integer]
sub_Carry 0 [] [] = []
sub_Carry c x [] = sub_Carry c x [0]
sub_Carry c (x : xs) (y : ys)
            | (x - y - c) < 0 = (10   x - y - c) : sub_Carry 1 xs ys
            | otherwise = (x - y - c ) : sub_Carry 0 xs ys

sub :: [Integer] -> [Integer] -> [Integer]
sub op1 op2
       | to_Integer(op1) == to_Integer(op2) = [0]
       | to_Integer(op1) > to_Integer(op2) = drop_Zeros (reverse (sub_Carry 0 (reverse op1) (reverse op2)))
       | otherwise = [-1]    drop_Zeros (reverse (sub_Carry 0 (reverse op2) (reverse op1)))
  • Related