Search code examples
cchecksum

Checksum for binary numbers? Converting back to decimal?


Introduction

This program should input a number in decimal (base 10) from the user, convert that number to binary, calculate the "binary sum", then present the binary sum and binary representation of the input.

The program should go something like this:

What type of display do you want?
Enter 1 for character parity, 2 for integer checksum: 2
Enter an integer for checksum calculation:  1024
Integer: 1024, Bit representation: 00000000 00000000 00000100 00000000 
Sum of the number is: 4
Checksum of the number is: 4, Bit representation: 00000100 

What is binary sum?

The "binary sum" of a number, n, is defined splitting the binary representation of n into 8-bit long numbers, and summing the base-10 value of each. This means 32-bit long numbers, you sum the base-10 values of the numbers represented by bits (1-8), (9-16), (17-24), and (25-32). Here is an example:

Example of binary sum of 1234567:

Step 1:
Convert 1234567 into it's binary representation.
1234567 -> 100101101011010000111

Step 2:
Split the binary number into 8 bit parts, adding zero's to the left if needed to make complete 8-bit numbers.
100101101011010000111 -> 00010010 11010110 10000111

Step 3:
Convert each 8-bit long number to decimal then add their values.

00010010 -> 18 (2^1 + 2^4 => 2 + 16 = 18)
11010110 -> 214 (2^1 + 2^2 + 2^4 + 2^6 + 2^7 => 2 + 4 + 16 + 64 + 128) = 214
10000111 -> 135 (2^0 + 2^1 + 2^2 + 2^7 => 1 + 2 + 4 + 128) = 135

18 + 214 + 135 = 367

The binary sum of 1234567 is 367.


I have no problem showing the binary representation of the input, but I'm not sure on how calculate the binary sum. This is challenging because I'm not allowed to use strings or arrays, only basic primitive data types.

This the code I have made so far, with comments where I am having issues:

int main(void) {

    char endLoop;
    int userChoice;
    char choice1;
    char byte; 
    int choice2;

    while(endLoop != 'q') {

        printf("\nWhat type of display do you want?");
        printf("\nEnter 1 for character parity, 2 for integer checksum: ");
        scanf("%d", &userChoice); 

        if(userChoice == 1) {
            printf("Enter a character for parity calculation: ");
            scanf(" %c", &choice1);
            printf("Character: %c" , choice1);
            printf(", Bit Representation: ");

            int number1s = fromBinary(toBinary(choice1, 8));

            printf("\nNumber of ones: %d", number1s);
            printf("\nEven 1 parity for the character is: ");

            if(number1s % 2 != 0) {
                printf("1");
                toBinary(choice1, 7);
            } else {
                toBinary(choice1, 8);
            }

        }
  
        if(userChoice == 2) {
            printf("Enter an integer for checksum calculation: ");
            scanf("%d", &choice2);
            printf("Integer: %d", choice2);
            printf(", Bit Representation: " );
            toBinary(choice2, 32);

            printf("\nSum of number is: ");
            printf("\nChecksum of number is: ");
            printf(", Bit Representation: ");

        } 
 
        printf("\n\nEnter r to repeat, q to quit: ");
        scanf(" %c", &endLoop);
    
    }

}

int toBinary(int userInput, int bits) {
    int i;
    int mask = 1 << bits - 1;
    int count = 0;

    for (i = 1; i <= bits; i++) {

        if (userInput & mask){
            count++;
           putchar('1');
        } else {
            putchar('0');
        }

        userInput <<= 1;
        
        if (! (i % 8)) {
            putchar(' ');
        }    
    }

    return count;

}  

int fromBinary(char binaryValue) {
   // I wanted to take the binary value I get from toBinary() and
   // convert it to decimal here. But am not sure how to go about it
   // since I need the bit representation, and I don't store the bit
   // representation, I only print it out.

   // I need to convert it to decimal so that I can add the decimal
   // values up to calculate the binary sum.
}

Solution


  • EDIT for negative inputs

    You have said that you would also like to handle negative numbers. The simplest way to do this, is to define your method to accept an unsigned int rather than an int. This will allow you to do all your normal bit operations without worrying about handling different cases for negative numbers.

    Change this line

    int getSum(int n) {
    

    to this

    int getSum(unsigned int n) {
    

    No further changes are necessary, in fact now we can remove the if statement in getSum.

    The new complete getSum method has been updated below. The commented code can be found at the bottom.

    Remember, if you want to print out an unsigned int, the format specifier is %u not %d.


    Solution

    If you have a number, and you want to add up the values of what each 8 bits of that number would be in base 10, you can do it like this:

    int getSum(unsigned int n) {
        int total = 0;
    
        while(n) {
            int tempCount = 0, i = 0;
    
            for(i = 0; n && i < 8; i++) {
                tempCount += (n & 1) * pow(2, i);
                n >>= 1;
            }
    
            total += tempCount
        }
    
        return total;
    }
    

    Explanation

    This code will (while n > 0) grab 8 bits at a time, and add their base-10 values:

    2^0 * 1 or 2^0 * 0 +
    2^1 * 1 or 2^1 * 0 + 
    2^2 * 1 or 2^2 * 0 +
        ... +
    2^7 * 1 or 2^7 * 0 
    

    tempCount holds the sum for each set of 8 bits, and after each 8 bits, tempCount is added to the total and is reset to 0.

    The condition in the for loop, n && i < 8 is of course to stop after grabbing 8 bits, but to also terminate early if n is 0.


    Testing

    This output:

    getSum(1025) = 5
    getSum(2048) = 8
    getSum(1234567) = 367
    getSum(2147483647) = 892
    

    was used to verify the correctness of this code:

    #include <stdio.h>
    #include <math.h>
    
    int getSum(unsigned int n) {
        int total = 0;
    
        //printf("passed in %u\n", n);
    
    
        while(n) {
          int tempCount = 0, i;
    
         //printf("n starts while as %u\n", n);
    
    
    
          // Take up to 8 bits from the right side of the number
          // and add together their original values (1, 2, 4, ..., 64, 128)
          for(i = 0; n && i < 8; i++) {
            //printf("\t\tn in for as %u\n", n);
            tempCount += (n & 1) * pow(2, i);
            //printf("\t\t\tbit is %u\n", (n & 1));
            n >>= 1;
          }
    
          //printf("\tAdded %u from that set of 8 bits\n", tempCount);
    
          total += tempCount;
        }
    
        return total;
    }
    
    int main(void) {
    
        printf("getSum(1025) = %d\n", getSum(1025));
        printf("getSum(2048) = %d\n", getSum(2048));
        printf("getSum(1234567) = %d\n", getSum(1234567));
        printf("getSum(2147483647) = %d\n", getSum(2147483647));
    
        return 0;
    }
    

    Of course I checked these examples by hand:

    2147483647

    2147483647 == 01111111 11111111 11111111 11111111
    The bit sum = 
           01111111 + 11111111 + 11111111 + 11111111 =
           127 + 255 + 255 + 255 = 892
    getSum(2147483647) = 892
    

    1025

    1025 == 00000100 00000001
    The bit sum = 
           00000100 + 00000001 = 
           4 + 1 = 5
    getSum(1025) = 5
    

    2048

    2048 == 00001000 00000000
    The bit sum = 
           00001000 + 00000000 = 
           8 + 0 = 8
    getSum(2048) = 8
    

    1234567

    1234567 == 00010010 11010110 10000111
    The bit sum = 
           00010010 + 11010110 + 10000111 = 
           18 + 214 + 135 = 367
    getSum(1234567) = 367
    

    -1

    -1 = 11111111 11111111 11111111 11111111
    The bit sum = 
           11111111 + 11111111 + 11111111 + 11111111 =
           255 + 255 + 255 + 255 = 1020
    getSum(-1) = 1020