二进制数的校验和?转换回十进制?

Checksum for binary numbers? Converting back to decimal?

简介

此程序应从用户输入一个十进制数(以 10 为底),将该数转换为二进制数,计算 “二进制和”,然后给出二进制和和输入的二进制表示。

程序应该是这样的:

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 

什么是 binary sum

一个数 n“二进制和” 定义为拆分 n 转换成 8 位长数字,并将每个数字的基数为 10 的值相加。这意味着 32 位长数字,您将位 (1-8)、(9-16)、(17-24) 和 (25-32) 表示的数字的以 10 为底的值相加。这是一个例子:

1234567的二进制和的例子:

第 1 步:
将 1234567 转换成它的二进制表示形式。
1234567 -> 100101101011010000111

第 2 步:
将二进制数拆分为 8 位部分,如果需要,则在左侧添加零以构成完整的 8 位数字。
100101101011010000111 -> 00010010 11010110 10000111

第 3 步:
将每个 8 位长数字转换为十进制,然后将它们的值相加。

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

1234567的二进制和为367.


显示输入的二进制表示没有问题,但我不确定如何计算二进制和。这很有挑战性,因为我不允许使用字符串或数组,只能使用基本原始数据类型。

这是我到目前为止所做的代码,在我遇到问题的地方进行评论:

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

编辑负输入

您说过您也想处理负数。最简单的方法是定义您的方法以接受 unsigned int 而不是 int。这将允许您执行所有正常的位操作,而不必担心处理负数的不同情况。

更改此行

int getSum(int n) {

至此

int getSum(unsigned int n) {

无需进一步更改,事实上现在我们可以删除 getSum 中的 if 语句。

下面更新了新的完整 getSum 方法。注释的代码可以在底部找到。

记住,如果要打印 unsigned int,格式说明符是 %u 而不是 %d


解决方案

如果您有一个数字,并且想将该数字的每 8 位以 10 为基数的值相加,您可以这样做:

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;
}

说明

此代码将(当 n > 0 时)一次获取 8 位,并添加它们的以 10 为底的值:

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 保存每组 8 位的总和,并且在每 8 位之后,tempCount 被添加到 total 并重置为 0

for循环中的条件,n && i < 8当然是抢到8位就停止,但是如果n为0也提前结束


测试

这个输出:

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

用于验证此代码的正确性:

#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;
}

当然是我亲手检查了这些例子:

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