Search code examples
cwhile-loopbinarybinary-operators

While loop iterates itself more or less than it should


Anwers of Austin Hastings and Michael Burr has solved my problem, this loop is always true as I just realised and it's solved when did it like Austin Hastings did. Cannot mark as answer since it is a comment. Thanks for your help!

I have an assignment in C which is to print only specific kinds of numbers between an 128 and 255 (so 8 digit binary representations) and I should do it without using any arithmetic operators. The conditions are:

  1. Number's binary representation has to have same number of 0's and 1's.
  2. Number's binary representation cannot have more 0's than 1's at any moment when reading from left-to-right. For example, 156 (1001 1100) does not meet the 2nd condition because there are two 0's and only one 1 at the 3rd digit, while 210 (1101 0010) satisfies these conditions.

I am using functional implementation and used a single function for these two conditions and that part of code is:

int checkOneToZero(unsigned int num) {
    unsigned int carry = 7, 
        counterOne = 0, 
        counterZero = 0, 
        ct = 0;

    while ((carry > 0) || (carry == 0)) {
        if ((num >> carry) & 1) {
            counterOne = binaryAddition(counterOne, 1);
            ct ++;
            printf(" %d ", ct); 
        }
        else {
            counterZero = binaryAddition(counterZero, 1);
            ct ++;
            printf(" %d ", ct); 
        }

        carry = binarySubtraction(carry, 1);
        printf(" CARRY %d \n", carry);

        if (counterZero > counterOne) {
            printf(" breakCounterZero %d breakCounterOne %d ", counterZero, counterOne);
            return 0;
        }
    }

    printf("successCounterZero = %d successCounterOne = %d", counterZero, counterOne);

    if (counterZero == counterOne)
        return 1;

    return 0;
}

I had wrong output constantly so put some control mechanisms which do not effect the code to track the problem. These are:

  • ct : Counts how many times it has enter into if or else in while loop.

  • printf(" CARRY %d \n", carry) : shows carry's value after it has been decreased one.

  • printf(" breakCounterZero = &d breakCounterOne = %d ") : shows 0 and 1 counts if it has stuck at "if (counterZero > counterOne)" which checks 0 count cannot be higher than 1 count at the end of each while loop.

  • printf("successCounterZero = %d successCounterOne = %d") : shows if it has passed the while loop.

My problem is if I try to let while loop work until carry is used last with carry = 0, it gives output of 210, which should work as it loops 8 times and at CARRY = -1 it should break from the loop while it is like:

1  CARRY 6
2  CARRY 5
3  CARRY 4
4  CARRY 3
5  CARRY 2
6  CARRY 1
7  CARRY 0
8  CARRY -1
9  CARRY -2
breakCounterZero 5 breakCounterOne 4

so it loops 1 more time than it should and it makes count one more 0 so it fails. But wen I increased limit of carry to 1 in while loop to see what happens, it gives:

1  CARRY 6
2  CARRY 5
3  CARRY 4
4  CARRY 3
5  CARRY 2
6  CARRY 1
7  CARRY 0
successCounterZero = 3 successCounterOne = 4

so it passes the 3rd condition but one less 0 than it should so fails at 2nd condition.

This seems to be a complicated and a too-specific question, but thanks for any hints.


Solution

  • I'm not sure about your binaryAddition and binarySubtraction functions - whether you are required to use them, or simply are using them to meet the condition that no arithmetic operations be used.

    For this simple case, it's worth pointing out that you can "count" up to 31 using the bits in an integer. Certainly enough to handle 8 possible values:

    int checkOneToZero(unsigned num) 
    {
        unsigned count_0s = 0;
        unsigned count_1s = 0;
    
        // Using a 'for' loop here because I know the start, stop, and update.
        for (unsigned check_bit = 1 << 7; check_bit; check_bit >>= 1) {
            if (num & check_bit) {
                /* ++count_1s; */
                count_1s |= (count_1s << 1) | 1;
            }
            else {
                /* ++count_0s; */
                count_0s |= (count_0s << 1) | 1;
    
                if (count_0s > count_1s) return 0;
            }
        }
    
        return count_0s == count_1s;
    }