以下代码未经严格论证仅供参考.
1.
题目描述
定义ilog2函数 - 返回 floor(log base 2 of x), x > 0 (即求以2为底x的对数,且向下取整)
函数原型为:int ilog2(int x);
例如:ilog2(17) = 4
main函数已经写好了,请根据main函数的内容完成该函数的设计:
int main(){
int x;
scanf("%d",&x);
printf("%d\n",ilog2(x));
return 0;
}
思路:
求log2(x),无非就是看看这个数能被二除几次,向下取整则当被除数为一时不记录。
AC code:
int ilog2(int x)
{
int cnt = 0;
while(x)
{
x >>= 1;
cnt ++;
if(x == 1)break;
}
return cnt;
}
2.
题目描述
设计一个isLessOrEqual函数,在不使用任何关系运算符的情况下,判断x <= y是否成立,成立则返回1,否则返回0
函数原型为:int isLessOrEqual(int x, int y);
例如:isLessOrEqual(4, 5) = 1
main函数已经写好,请根据main函数的内容完成该函数的设计:
int main(){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",isLessOrEqual(x,y));
return 0;
}
思路:
对于 x == y ,我们可以直接用 ^(异或)来判断,可以知道,当且仅当x == y 时,有 x ^ y == 0 ;那么对于 x < y 的判断,我们可以从符号位入手,可以知道,当 x < y 时, x - y < 0, 此时符号位为 1 ,此题的数据类型为 int 类型,总共 32 位,我们检查一下 x - y 的最高位是否为 1 即可。
AC code:
int isLessOrEqual(int x, int y)
{
return (!(x ^ y) || ((x - y) >> 31) & 1);
}
3.
题目描述
定义一个函数,在不使用任何关系运算符的情况下,对参数x的符号进行判断,如果大于0则返回1,否则返回1
函数原型为:int isPositive(int x);
例如:isPositive(-1) = 0
main函数已经写好了,请根据main函数的内容完成该函数的设计:
int main(){
int x;
scanf("%d",&x);
printf("%d\n",isPositive(x));
return 0;
}
输入描述
输入x
输出描述
输出函数的返回值
提示
你需要提交main函数之外的代码
***请不要使用任何关系运算符***
思路:
如果解决了上一问,这一问应该很好解决,检查最高位是否为 1 即可,需要注意的是0的特判。
AC code:
int isPositive(int x)
{
return (!(((x >> 31) & 1)) && x);
}
4.
题目描述
设计一个bitAnd函数,在不使用按位与运算符&的情况下,实现按位与运算,可以使用按位取反~和按位或|
函数原型为:int bitAnd(int x, int y);
例如:bitAnd(6, 5) = 4
main函数已经写好了,请根据main函数的内容完成该函数的设计:
int main(){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",bitAnd(x,y));
return 0;
}
思路:
此题考察的是位运算符号的等价计算,对于 x & y 我们得到的是两者皆有1的部分,我们能用的只有 | 与 ~, | 是进行留 1 的操作,而 ~ 是进行 全部取反的操作,以此我们可以推出
~( ~x | ~y ) == x & y 此式恒成立
AC代码:
int bitAnd(int x, int y)
{
return ~(~x | ~y);
}
5.
题目描述
设计一个函数,在不使用负号的情况下,返回-x
函数原型为:int negate(int x);
例如:negate(1) = -1
main函数已经写好了,请根据main函数的内容完成该类的设计:
int main(){
int x;
scanf("%d",&x);
printf("%d\n",negate(x));
return 0;
}
输入描述
输入x
输出描述
输出函数的返回值
提示
本题需要提交完整的程序
***请不要直接使用负号运算符***
思路:
补码思想,取反加一。
AC code:
#include<stdio.h>
int negate(int x)
{
return (~ x) + 1;
}
int main(){
int x;
scanf("%d",&x);
printf("%d\n",negate(x));
return 0;
}
6.
题目描述
定义一个函数,在不使用逻辑非运算符!的情况下,用于求!x
函数原型为:int bang(int x);
例如:bang(5) = 0, bang(0) = 1
main函数已经写好了,请根据main函数的内容完成该函数的设计:
int main(){
int x;
scanf("%d",&x);
printf("%d\n",bang(x));
return 0;
}
思路:
逻辑运算下只有 0 和 1,考虑 0 和非零的情况即可
AC code:
int bang(int x)
{
return (~x) == -1;
}
7.
题目描述
定义divpwr2函数,在不使用除法运算符的情况下,计算 x/(2^n),0 <= n <= 30,要求向 0 舍入
例如:divpwr2(15, 1) = 7, divpwr2(-33, 4) = -2
main函数已经写好了,请根据main函数的内容完成该函数的设计:
int main(){
int x,n;
scanf("%d%d",&x,&n);
printf("%d\n",divpwr2(x,n));
return 0;
}
思路:
对于正数的情况,C语言是默认下取整,所以我们只需要考虑负数时怎么向零舍入
AC code:
int divpwr2(int x, int n)
{
while(n --)
{
x >>= 1;
}
return x + (x < 0 && x & 1);
}
8.
题目描述
设计一个函数,该函数将给定的任意整型数据视为一个IPv4地址,并以点分十进制形式显示该IP地址。
例如:整数为-1455049865(十六进制表示为0xA945B377),对应的IP地址为:169.69.179.119。
函数原型为:void showIP(int x);
main函数已经写好了,请根据main函数的内容完成该函数的设计:
int main(){
int x;
scanf("%d",&x);
showIP(x);
return 0;
}
思路:
只需要记得,点分十进制如何表示即可,在十六进制下,每两位十六进制数对应一个点,所以我们把十六进制分开处理就行了
AC code:
void showIP(int x)
{
int cnt = 7;
int ans = 0;
for(int i = 31; i >= 7; i -= 8)
{
ans = 0;
cnt = 7;
for(int j = i; j > i - 8; j --)
{
ans += (((x >> j) & 1) << cnt);
cnt --;
}
if(i != 7)
printf("%d.", ans);
else
printf("%d", ans);
}
}
9.
题目描述
设计一个函数,用于测试参数x是否能被n位补码整数表示(1 <= n <= 32)。如果能返回1,否则返回0
函数原型为:int fitsBits(int x, int n);
例如: fitsBits(5, 3) = 0, fitsBits(-4, 3) = 1
main函数已经写好了,请根据main函数内容完成该函数的设计:
int main(){
int x,n;
scanf("%d%d",&x,&n);
printf("%d\n",fitsBits(x,n));
return 0;
}
思路:
我们检查一下每个 x 是否在 n 位补码整数的范围即可,首先注意对于32位的补码非负整数,我们最多使用31位,其中最高位依旧为符号位为0,而负数能使用32位,所有分开讨论即可;特别注意溢出问题:负数移位溢出之后的值一律为-1,正数移位溢出之后的值一律为0.
AC code:
int fitsBits(int x, int n)
{
if(x >= 0)
return (x > 1 << (n - 2)) ? 0 : 1;
if(x < 0)
return (x < -1 << (n - 1)) ? 0 : 1;
}
10.
题目描述
设计一个函数,返回长度为n位(1<=n<=32)的无符号整数能表示的最大值。
函数原型为:unsigned umax(int n);
例如: umax(3)=7,umax(6)=63;
main函数已经写好了,请根据main函数内容完成该函数的设计:
int main(){
int n;
scanf("%d",&n);
printf("%u\n",umax(n));
return 0;
}
思路:
直接做 n 次左移位运算,最后结果减 1 即可.
AC code:
int umax(int n)
{
int x = 1;
while(n --)
{
x <<= 1;
}
return x - 1;
}
11.
设计一个函数,返回长度为n位(2<=n<=32)的有符号整数能表示的最大正数。
函数原型为:int tmax(int n);
例如: tmax(3)=3,tmax(6)=31;
main函数已经写好了,请根据main函数内容完成该函数的设计:
int main(){
int n;
scanf("%d",&n);
printf("%d\n",tmax(n));
return 0;
}
思路:
与上一题一致,唯一变化的是多了一位符号位,所以我们处理时要先把 n 减去 1.
AC code:
int tmax(int n)
{
n --;
int x = 1;
while(n --)
{
x <<= 1;
}
return x - 1;
}
12.
题目描述
设计一个函数,返回长度为n位(1<=n<=32)的有符号整数能表示的最小负数。
函数原型为:int tmin(int n);
例如: tmin(3)=-4,tmin(6)=-32;
main函数已经写好了,请根据main函数内容完成该函数的设计:
int main(){
int n;
scanf("%d",&n);
printf("%d\n",tmin(n));
return 0;
}
思路:
与上一题一致,但是结果可取最高位,返回负数即可.
AC code:
int tmin(int n)
{
n --;
int x = 1;
while(n --)
{
x <<= 1;
}
return -x;
}
13.
题目描述
设计一个函数,用于输出一个整型数据的32位二进制补码编码。
函数原型为:void twosComplement(int x);
例如:twosComplement(-1)的输出为:11111111111111111111111111111111
main函数已经写好了,请根据main函数的内容完成该函数的设计:
int main(){
int x;
scanf("%d",&x);
twosComplement(x);
return 0;
}
思路:
无论是什么数,其在计算机中都是以二进制储存,所以遍历每一位输出即可.
AC code:
#include<stdio.h>
int twosComplement(int x)
{
for(int i = 31; i >= 0; i --)
{
if((x >> i) & 1) printf("%d", 1);
else printf("%d", 0);
}
}
int main()
{
int x;
scanf("%d",&x);
twosComplement(x);
return 0;
}
14.
题目描述
设计一个函数,该函数返回一个整数数据的二进制镜像数。所谓二进制镜像数,是指二进制表示和该数的二进制表示正好逆序的数。
例如:二进制序列1010的逆序列是0101
函数原型为:int binMirror(int x);
例如:binMirror(1)=-2147483648
main函数已经写好了,请根据main函数的内容完成该函数的设计:
int main(){
int x;
scanf("%d",&x);
printf("%d\n",binMirror(x));
return 0;
}
思路:
正着遍历每一位,若位为 1 则附上权重,权重是反着赋的,最后注意此数类型为有符号数最高位为符号位,应该附上负权重.
AC code:
int binMirror(int x)
{
int ans = 0;
for(int i = 0, j = 31; i <= 31; i ++, j --)
{
if(i != 31)
if(((x >> i) & 1)) ans += (1 << j);
else
if(((x >> i) & 1)) ans -= (1 << j);
}
return ans;
}
15.
题目描述
设计一个函数,用于返回一个整型数据中1的个数。
函数原型为:int bitCount(int x);
例如:bitCount(5) = 2, bitCount(7) = 3
main函数已经写好,请根据main函数的内容完成该函数的设计:
int main(){
int x;
scanf("%d",&x);
printf("%d\n",bitCount(x));
return 0;
}
思路:
遍历每一位,是 1 答案就加1.
AC code:
int bitCount(int x)
{
int l = 0;
for(int i = 0; i < 32; i ++)
{
if((x >> i) & 1) l ++;
}
return l;
}
16.
题目描述
对有符号整型数据使用>>右移运算符进行操作进行的是算术右移。现在请设计一个函数,要求对有符号整型数据进行逻辑右移。
该函数的原型是:int logicalShift(int x, int n);(0<=n<=31)
例如:logicalShift(0x87654321,4) 的结果应该为 0x08765432
main函数已经写好了,请根据main函数的情况完成该函数的设计:
int main(){
int x,n;
scanf("%x%d",&x,&n);
printf("%x\n",logicalShift(x,n));
return 0;
}
思路:
弄清什么是算术位移与逻辑位移,算数位移是保持符号位不变的位移,注意当处理数最高位为 1 时右移后最高位都补1,而逻辑位移是无论左右位移都补 0,对无符号的位移属于逻辑位移,所以我们只需要把所求数赋给无符号数即可.
AC code:
int logicalShift(int x, int n)
{
unsigned int t = x;
t >>= n;
x = (int) t;
}
17.
题目描述
设计一个函数:int getByte(int x, int n);
该函数将参数x的值的第n个字节取出(0 <= n <= 3)并返回
例如:getByte(0x12345678,1) = 0x56
main函数已经写好,请根据main函数的内容,完成该函数的设计:
int main(){
int x,n;
scanf("%x%d",&x,&n); //注意,x以16进制格式输入
printf("%x\n",getByte(x,n)); //结果以16机制格式输出
return 0;
}
思路:
一个字节 8 个 bit,一个十六进制有 4 个bit,两个个十六进制可以表示 1 个字节,所以按题目要求取出字节即可.
AC code:
int getByte(int x, int n)
{
int ans = 0, cnt = 0;
int t, k;
for(int i = n * 8, j = 0;i < (n + 1) * 8; i ++, j ++)
{
t = (x >> i) & 1;
k = t << j;
ans += k;
}
return ans;
}
18.
题目描述
设计一个函数:int clearMask(int x, int n);
该函数将参数x的值的第n位设置为0(0 <= n <= 31)并返回新的值
例如:clearMask(7, 5) = 7
main函数已经写好,请根据main函数的内容,完成该函数的设计:
int main(){
int x,n;
scanf("%d%d",&x,&n);
printf("%d\n",clearMask(x,n));
return 0;
}
思路:
遍历每位,当到第 n 位不计算.
AC code:
int clearMask(int x, int n)
{
int ans = 0;
for(int i = 0; i < 32; i ++)
{
if((x >> i) & 1 && i != n)
{
ans += (1 << i);
}
}
return ans;
}
19.
题目描述
设计一个函数:int setMask(int x, int n);
该函数将参数x的值的第n位设置为1(0 <= n <= 31)并返回新的值
例如:setMask(7, 5) = 39
main函数已经写好,请根据main函数的内容,完成该函数的设计:
int main(){
int x,n;
scanf("%d%d",&x,&n);
printf("%d\n",setMask(x,n));
return 0;
}
思路:
与上题一样的处理方法.
AC code:
int setMask(int x, int n)
{
int ans = 0;
for(int i = 0; i < 32; i ++)
{
if((x >> i) & 1 || i == n)
{
ans += (1 << i);
}
}
return ans;
}