简介
进一步理解书中第二章《信息的表示和处理》部分的内容,深刻理解整数、浮点数的表示
和运算方法,掌握GNU GCC工具集的基本使用方法。
要求
请按照要求补全 bits.c 中的函数,并进行验证。包括以下6个函数 :
1. int isAsciiDigit(int x)
功能:当0x30<=x<=0x39时(即字符0-9的ASCII码值)返回1;其他情况下返回0
示例:isAsciiDigit(0x35) = 1
isAsciiDigit(0x3a) = 0
isAsciiDigit(0x05) = 0
难度:3
可使用运算符数:15
int isAsciiDigit(int x) {
int up_num = x + (~58 + 1); //最高位为1
int low_num = x + (~48 + 1); //最高位是0
int Is_up_legal = (!((up_num >> 31) + 1));
int Is_down_legal = ((low_num >> 31) + 1);
return (Is_up_legal & Is_down_legal);
}
In this function, what we should to do is to judge weather the 'x' is bigger than 48(inclusive) and smaller than 57(inclusive).
first:
we mapping the legal-x:
up_num = x -58;
low_num = x - 48;
we will get (up_num < 0) and (low_num >= 0) if the "x" is legal.
then:
"(( up_num >> 31) + 1)" will be equal to 0 ,if (up_num < 0).
"((low_num >> 31) + 1)" will be equal to 1 ,if (low_num >= 0).
so,if (up_num < 0), "Is_up_legal" will be equal to 1.if (low_num >= 0),"Is_down_legal" will be equal to 1.
last:
only if ((up_num >> 31) + 1) == 0 and ((low_num >> 31) + 1), we return 1;
2. int anyEvenBit(int x)
功能:当x的任意偶数位为1时,返回1;其他情况下返回0
示例:anyEvenBit(0xA) = 0
anyEvenBit(0xE) = 1
难度:2
可使用运算符数:12
int anyEvenBit(int x) {
int x1 = x >> 8;
int x2 = x1 >> 8;
int x3 = x2 >> 8;
return !!( ( x | x1 | x2 | x3 )& 0x55);
}
/*
每次我们移动8位,把移动的3次结果和x一起做|运算,相当于把每8个信息都重叠到最低的8位,
此时与01010101做&运算就可以知道其偶数位是否是1.
*/
3. int copyLSB(int x)
功能:将返回值中的所有位全部置位成x中的第0位的值
示例:copyLSB(5) = 0xFFFFFFFF, copyLSB(6) = 0x00000000
难度:2
可使用运算符数:5
int copyLSB(int x) {
int temp = x & 1;
return (~temp + 1);
}
/*
first, we could get least significant bit by used "x & 1".
then, we could get result
*/
4. int leastBitPos(int x)
功能:返回一个掩码,在该掩码中标识了二进制数x的所有位中,“1”所在的位权最小的位
示例:leastBitPos(0x60) = 0x20
难度:2
可使用运算符数:6
int leastBitPos(int x) {
return (~x+1) & x;
}
/*
we get the "-x",than "(-x)&x" is what we need.
*/
5. int divpwr2(int x, int n)
功能:计算 x / 2^n,并将结果取整
示例:divpwr2(15,1) = 7
divpwr2(-33,4) = -2
难度:2
可使用运算符数:15
int divpwr2(int x, int n) {
int op = (x >> 31) + 1;
int temp = x >> n;
int temp2 = temp << n;
int Is_exact_division = !!(temp2 ^ x);
return (temp + ( (!op) & (!!n) & (Is_exact_division) ) );
}
/*
一般来说,“>>”符号代表 x/(2^n),并向下取整(无论正负)。
所以有三种情况需要考虑:
如果负数,需要向上取整。
如果 n=0 应该为 x。
如果能够整除,就不需要取整操作。
此题中,op是符号标志位,正数为1,负数为0.
temp为x右移动n位结果,相当直接 x/(2^n) ,向下取整。
temp2为temp左移动n位结果,利用(temp2 ^ x),可以判断temp舍弃的几位是否都是0(既能否整除)。
Is_exact_division 代表如果能整除为0,反之为1。
因为>>默认代表向下取整,所以我们需要考虑上述情况,利用 (!op) & (!!n) & (Is_exact_division)实现,
其含义:同时满足 (负数)(n!=0)(不能整除) 三种情况返回1,否则返回0。
也意味着,满足上述三情况才需要在向下取整的前提+1,否则向下取整结果就是正常取整结果。
*/
6. int bitCount(int x)
功能:计算二进制数x中,对应位值“1”的总位数
示例:bitCount(5) = 2
bitCount(7) = 3
难度:4
可使用运算符数:40
int bitCount(int x) {
int mask = (0x11 <<24) | (0x11 << 16) | (0x11 << 8) |(0x11) ;
int temp = x & mask;
x = x >> 1;
temp = temp + (x & mask);
x = x >> 1;
temp = temp + (x & mask);
x = x >> 1;
temp = temp + (x & mask);
return ((temp & 0xf) +
( (temp >> 4) & 0xf )+
( (temp >> 8) & 0xf )+
( (temp >> 12) & 0xf )+
( (temp >> 16) & 0xf )+
( (temp >> 20) & 0xf )+
( (temp >> 24) & 0xf )+
( (temp >> 28) & 0xf ));
}
/*首先分割成4块,每块右移动,同时比较每个块的1的个数*/
tip:程序内允许使用:
a. 运算符: ! ~ & ^ | + << >>
b. 范围在0 - 255之间的常数
c. 局部变量
tip:程序内禁止以下行为:
a. 声明和使用全局变量
b. 声明和使用定义宏
c. 声明和调用其他的函数
d. 类型的强制转换
e. 使用许可范围之外的运算符
f . 使用控制跳转语句:if else switch do while for
注意:违背以上原则均视为程序不正确!!