Task 2: GCD(A,B)
这个task要求我们获取两个数(均小于等于10000000)的最大公约数,因此我使用了辗转相除法。
#include<stdio.h>
int main(){
int A=0, B=0, C=0;
printf("input two integers:\n");
scanf("%d %d", &A, &B);//获得两个输入的数值
while (B > 0)//当余数为0时截止循环
{
C = A%B;//取余数
A = B;//A取除数的值
B = C;//B取余数的值
}
printf("The GND of A and B is %d", A);
return 0;
}
Task 6: Fibonacci sequence
这是代码,我选择用递归的方式进行计算。
int addition(N)
{
if (N > 1)
{ //根据斐波那契数列的性质,第N个数等于第N-1个和第N-2个数的和
return addition(N-1)+addition(N-2);
}
else if (N == 1)//根据规定,斐波那契数列的第一个数为1
{
return 1;
}
else if (N == 0)//为了保证准确性,设置第0个数为0
{
return 0;
}
}
int main()
{
int N = 0, res = 0;
printf("Input an integer positive:");
scanf("%d", &N);
res = addition(N);
printf("The %dth Fibonacci Number is %d",N,res);
return 0;
}
同时我也写了迭代方式的代码,并获得了同样结果;
#include <stdio.h>
int main()
{
int n=0,count=1,num1=0,num2=1;
printf("Input a positive integer:");
scanf("%d",&n);
while (count<n)//用来计数做了多少次递归
{
num2 = num2 + num1;//获得数列的下一个数
num1 = num2 - num1;//保存上一个数
count++;
}
printf("the %dth number is %d",n,num2);
return 0;
}
Task 4: abs(n)
本题要求使用位运算来求一个整数n的绝对值。
一个整数默认位数为32位,因此按位向右移31位后,即可获得该数的符号,即0为正数,-1为负数。若x为正数,y就为0,xy就还是x本身(因为10=1,0^0=0);若x为负数,y就为-1,而与-1异或相当于取反,再加上1(即减去-1)即获得负数的绝对值。
#include <stdio.h>
int main()
{
int x,y;
printf("Input an integer:");
scanf("%d", &x);
y = x >> 31;//获取x的符号,整数或者负数
y = (x ^ y) - y;//使用按位异或来进行获取
printf("The abs of x is %d",y);
return 0 ;
}
Task 5: m o d ( m , 2 n ) mod(m,2^n) mod(m,2n)
本题要求使用位运算,求 m o d ( m , 2 n ) mod(m,2^n) mod(m,2n) 的值。
首先根据输入的 m , n m,n m,n通过位运算 1 < < n 1<<n 1<<n 获得 2 n 2^n 2n在二进制中的表达式,该数-1则获得了由n个1组成的数。
以 m = 17 , n = 3 m=17,n=3 m=17,n=3为例,
第一步我们通过按位向右获得了 i = 1000 i = 1000 i=1000, m = 10001 m=10001 m=10001。
随后我们通过 i − 1 = 111 i-1=111 i−1=111,并根据按位与获得了 l = 00001 l=00001 l=00001
#include <stdio.h>
int main(){
int m,n,l;
printf("Input two integers:");
scanf("%d %d", &m, &n);
int i = 1 << n;//获得2^n对应的二进制值
l = m & (i-1);//获得l中第i位无法被2的i次方整除的部分
printf("The mod is %d", l);
return 0;
}
Task 7 Hamming Weight
这是我的代码,在代码中我使用了按位与来进行1的统计。因为使用可以将 x = x & ( x − 1 ) x=x\&(x-1) x=x&(x−1)二进制表达式中最右边的1去掉。以 x = 20 x=20 x=20为例:
x x x的二进制表达式为 00010100 0001 0100 00010100 , x − 1 = 00010011 x-1 = 00010011 x−1=00010011, x & ( x − 1 ) = 00010000 x\&(x-1)=00010000 x&(x−1)=00010000 这样就去掉了最右边的1。而循环的终止条件为 x x x 中的所有1都被去掉,此时 x = 0 x=0 x=0.
#include <stdio.h>
int main()
{
unsigned int x,count=0;//x为输入数字,count用来计数
printf("Input an integer:");
scanf("%d",&x);
while (x>0)//终止条件为x=0
{
x = x&(x-1);//去掉最右边的1
count++;//进行计数,没去掉一个1,count会加1
}
printf("There are %d one.",count);//打印结果
return 0;
}
Task 8 Grial(n)
本题与上面一题相似,在代码中使用按位或来进行统计。因为使用可以将 x = x ∣ ( x + 1 ) x=x|(x+1) x=x∣(x+1)二进制表达式中最右边的0去掉。以 x = 20 x=20 x=20为例:
x x x的二进制表达式为 10100 1 0100 10100 , x + 1 = 10101 x+1 = 10101 x+1=10101, x ∣ ( x + 1 ) = 10101 x|(x+1)=10101 x∣(x+1)=10101 这样最右边的0就变成了1。而循环的终止条件为 x x x 中的所有0都被去掉,此时按位取反后 x = 0 ~x=0 x=0.
但是要注意一点:一个Unsigned Int默认是32位的,因此根据之前的判断条件,最左边的1前面的0也会被记入,因此我们还需要一个循环来计算该数字的实际位数并做一步减法,因此我们使用了>>每按位向右一次计数一次,知道x变成0.
#include <stdio.h>
int main(){
unsigned int x,y,count1=0,count2=0;
printf("Input an integer:");
scanf("%d",&x);
y = x;
while (~x != 0)//用来计数x中0的个数,当x每位都为1时截止
{
x = x|(x+1);//把最右边的0变成1
count1 ++;//计数1
}
while (y != 0)//用来计数x的有效位数
{
y = y>>1;//按位向右
count2 ++;//计数1
}
printf("There are %d zeros.",count1+count2-32);//最终用所有的0减去有效位数前的0的个数
return 0;
}