最直观的方法
其实最直观的方法,就是如果x对i取余得0,表示x能由i整除,所以x就是i的倍数
if(x%i==0)
printf("%d是i的倍数\n",x)
但是我们这里肯定要讲别的方法
欧几里得
假如某个数是x的倍数,那么x就是两数之间的最大公约数,那么我们很容易想到欧几里得递归求最大公因数的方法
那我们根据这条性质求出x的倍数
int func(int a,int b)
{
return b==0?a:func(b,a%b);
}
int main(){
int N=1024;
int x=2;
for(int i=0;i<=N;i++)
//假如i是x的倍数
if(func(i,x)==x)
printf("%d\n",i);
}
位运算
没写好,随便看看吧
通过位运算也可以解决这类问题
先看几组运算
1111 1111
& 0000 0000
= 0000 0000
1111 1110
& 0000 0001
= 0000 0000
1111 1100
& 0000 0011
= 0000 0000
直观上来看,任何数&0都会得0,最低位为0的数&1都会得0,依次类推都成立
我们再延伸探讨一下,
第一组数据中,左值可以取任意的数
第二组数据中,左值同样可以取得任意的数,只要它的最低位是0
第三组数组中,…,只要最低两位都是0
…
再翻译成十进制
任意数都是1的倍数,成立
只要不是奇数的数都是2的倍数。仔细想想,在2进制中,如果最低位永远是0,没有1的存在,该数一定是奇数,就是说该数x可以表示成
C
1
∗
2
n
+
C
2
∗
2
n
−
1
+
.
.
.
+
C
n
∗
2
1
C_1*2^{n}+C_2*2^{n- 1}+...+C_n*2^{1}
C1∗2n+C2∗2n−1+...+Cn∗21的形式,可以发现该数一定能由2表示,这也是成立的 (通过这条性质我们还可以判断一个数的奇偶性)
第三组数据,0000 0011的值是3,那么某个数&3==0是什么意思呢?我们不妨列出这些数
0000 0100 --- 4
0000 1000 --- 8
0000 1100 --- 12
.... ..00 --- ..
发现只要是最低两位都不是1的数,它们都有一个性质,那就是它们一定是4的倍数。。。
那我们这下是不是可以做个推论,只要任意一个数&x为0,那么它一定是x的倍数
?
先验证一下把,我们查找6的倍数
0001 1000
& 0000 0110
= 0000 0000
正确,24是6的倍数
0000 1001
& 0000 0110
= 0000 0000
错了,9&6==0,但是9并不是6的倍数,找到一个反例,说明上面的结论是不正确的
这时候我们发现任意一个数&x为0
,是这个数是x的倍数
的必要条件,而不是充分条件。
再整理一下数据发现,右值的1必须是连续的,这时候我们才能说
对于某个特殊的x,如果某个数&x==0,那么该数一定是(x+1)的倍数。x的bit从低位开始必须是连续的1
继续验证一下,发现这条性质是成立的。但是对于这个特殊的x,如下面这种形式
0000 0001 --- 1 用于判断某个数是不是2的倍数
0000 0011 --- 3 用于判断某个数是不是4的倍数
0000 0111 --- 7 用于判断某个数是不是8的倍数...
.... ....
等于说现在又绕回来了 😂…这个方法其实只能判断某个数是不是X的倍数,${ X | 2^c,(c=1,2…n) } $
写了一大堆。。也算是个扩展思路的方法把😂😂
int main(){
//查找2的倍数
int N=1024;
for(int i=0;i<=N;i++)
if((i&0x01)==0)
printf("%d\n",i);
}