这两天有人问我一个问题:假设给定一个正整数x(0 < x < 10^6),将x转化成对应的二进制,其中含有n个1;令正整数y > x,将y转化成二进制后,同样含有n个1。求:y的最小值。
举个例子:
15对应的二进制是:1111
23对应的二进制是:10111
若x = 15,则y的最小值是23。
我们探讨一下十进制转二进制的方法:
1、不断除以2,并记录余数;
2、逆序输出得到的余数。
举个例子:
求23对应的二进制:
23 ÷ 2 = 11 余 1
11 ÷ 2 = 5 余 1
5 ÷ 2 = 2 余 1
2 ÷ 2 = 1 余 0
1 ÷ 2 = 0 余 1
将余数逆序输出:10111。
如果将二进制转化成十进制,则可以使用加权求和方法:
求1011对应的十进制
位序: 3 2 1 0
二进制:1 0 1 1
权重: 2^3 2^2 2^1 2^0
接下来将每一位的二进制数字乘以权重,最后求和,得到对应十进制:
2^3 * 1 + 2^2 * 0 + 2^1 * 1 + 2^0 * 1 = 8 + 0 + 2 + 1 = 11
(文章最后一部分是十进制与二进制相互转化的程序。)
那么,回到题目,求解该题目的程序如下:
#include<stdio.h>
int First_Function(int N) {
int count = 0;
while (N) {
count += (N & 1);
N >>= 1;
}
return count;
}
int Second_Function(int N) {
int j = First_Function(N);
for (int i = N + 1; i < 1000000; i++) {
if (j == First_Function(i)) {
return i;
}
}
}
int main() {
int N;
scanf("%d", &N);
printf("The result:%d", Second_Function(N));
return 0;
}
函数 First_Function() 用来计算用户输入正整数对应二进制数中含有 1 的个数。函数Second_Function() 中,假设用户输入的正整数是 N ,则变量 j 是 N 对应二进制中含有 1 的个数。令变量 i 从 N+1 开始递增,当变量 i 对应二进制中含有 1 的个数与 j 相等,则停止循环并返回变量 i 。
在 First_Function() 函数中有这样两行代码:
count += (N & 1);
N >>= 1;
其中符号 & 代表按位与运算:
按位与运算:
a b a&b
0 0 0
0 1 0
1 0 0
1 1 1
那么,假设 N 为 25 , N 对应的二进制数位 11001。N & 1 的计算过程为:
1 1 0 0 1
0 0 0 0 1
结果为: 0 0 0 0 1 (即N & 1 == 1)
N >>= 1 则表示 N 对应二进制数右移1位后的结果。同样假设N为25:
1 1 0 0 1
右移1位: 0 1 1 0 0 (即N >> 1 == 12(对应二进制是1100))
这样循环下去,即可得到N对应二进制中含有多少个1。
(当然,要知道 N 对应二进制中含有多少个1不止以上一种方法。在文章最后一部分二进制转十进制的程序中会有所提及。)
上面介绍了按位与运算 & 的计算方法,下面再说两个:按位或(|)、按位异或(^):
按位或运算:
a b a|b
0 0 0
0 1 1
1 0 1
1 1 1
按位异或运算:
a b a^b
0 0 0
0 1 1
1 0 1
1 1 0
总结起来就是:
按位与(&):全1得1(即只有当a 、b全是1时,a & b == 1);
按位或(|):有1得1(即当a 、b中只要有1,a | b == 1);
按位异或(^):全1全0均得0(即当a 、b全是1或全是0时,a ^ b == 0)。
十进制转二进制的c语言程序如下:
#include<stdio.h>
void print_binary(int n) {
if (n > 1) {
print_binary(n / 2);
}
printf("%d", n % 2);
}
int main() {
int decimal;
printf("Please input a decimal: ");
scanf("%d", &decimal);
printf("The binary representation of %d is : ", decimal);
print_binary(decimal);
printf("\n");
return 0;
}
二进制转十进制的c语言程序如下:
#include<stdio.h>
#include<string.h>
int binary_to_decimal(char* binary) {
int decimal = 0;
int length = strlen(binary);
for (int i = 0; i < length; i++) {
if (binary[i] == '1') {
decimal += 1 << (length - i - 1);
}
else if (binary[i] != '0') {
printf("Illegal input: Binary numbers can only contain 0 and 1!\n");
return -1;
}
}
return decimal;
}
int main() {
char binary[65];
printf("Please input a binary number: ");
if (scanf("%64s", binary) != 1) {
printf("Input error,unable to read valid binary number.\n");
return 1;
}
int decimal = binary_to_decimal(binary);
if (decimal != -1) {
printf("The decimal representation of %s is: %d.\n", binary, decimal);
}
return 0;
}
二进制转十进制还可以这样:
#include <stdio.h>
#include <math.h>
#define DIGITAL_NUM 65
long DecimalToBinary(char n[]);
int main() {
char num[DIGITAL_NUM];
printf("Input a binary number: ");
scanf("%s", num);
printf("Binary %s convert to decimal number is: %ld\n", num, DecimalToBinary(num));
return 0;
}
long DecimalToBinary(char n[]) {
long DecimalResult = 0;
int count = 0;
int t;
while (n[count] != '\0') {
count++;
}
for (int i = 0; i < count; i++) {
t = n[i] - '0';
DecimalResult += (int)pow(2, count - i - 1) * t;
}
return DecimalResult;
}
此外,如果只是想简单验证二进制与十进制之间转换的对不对,可以不采取以上复杂难懂的程序。以二进制转十进制为例:
#include<stdio.h>
int main(void) {
int binary = 0b1100;
printf("二进制1100的十进制值是:%d\n", binary);
return 0;
}
以上内容如有不妥之处,请大家批评指正!谢谢大家!