深入理解计算机系统作业0

以下代码未经严格论证仅供参考.

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

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值