C语言 - 判断任意数的每位数是否为偶数【两种方法】

本文提供两种方法来判断输入的六位数中每一位数字是否能被2整除。第一种方法通过逐个读取字符并检查每个数字的奇偶性;第二种方法使用整数运算实现相同目的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:判断任意数,没位数是否为偶数

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char ch, count = 0;
    int flag = 0;
    printf("请输入一个六位数:");
    while((ch = getchar()) != '\n')
    {
        if((ch-'0') % 2 != 0)
            count++;
    }
    if(count == 0)
        printf("全部都能被2整除\n");
    else
        printf("其中 %d 个不能被2整除\n", count);

    
    printf("\n");
    system("pause");
    return 0;
}



//第二种方法

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int a;
    printf("请输入一个六位数:");
    scanf("%d", &a);

    while(a)
    {
        a = a / 10;
        if(a % 2 == 0)
        {
            continue;
        }
        else
        {
            break;
        }
    }

    if(a == 0)
    {
        printf("全能被2整除!");
    }
    else
    {
        printf("不能全被2整除!");
    }
    
    printf("\n");
    system("pause");
    return 0;
}


<think>我们已知有三个二进制(每个变量只存储1位二进制),现在要合并成一个三位二进制(按顺序组合),然后左移一位,再重新拆分成三个二进制分别赋值给三个变量。根据问题,合并后的二进制是一个3位的二进制,左移一位后会变成4位(因为左移后最低位补0,最高位可能被移出),但我们要重新分配到三个变量,所以需要处理这个4位数的低三位?或者按照题目要求,我们可以选择保留低三位(即左移后,最高位移出,最低位补0,然后取低三位重新拆分)。但是原题并没有明确说明如何处理溢出位,所以我们默认只取低三位重新分配给三个变量。步骤如下:1.假设有三个变量:a,b,c(每个变量取值为0或1),分别表示二进制的第一位(最高位)、第二位、第三位(最低位)。2.合并成一个三位二进制:num=(a<<2)|(b<<1)|c;例如:a=1,b=0,c=1->num=1<<2|0<<1|1=4|0|1=5(二进制101)3.左移一位:num_shifted=num<<1;这样,5<<1=10(二进制1010),即十进制的10。4.由于左移后变成4位,我们需要重新拆分成三个二进制(只取移位后的低三位,即第0位(最低位)、第1位、第2位,而原来的最高位(第3位)被丢弃)。所以,从num_shifted中提取:a_new=(num_shifted>>2)&1;//取第2位b_new=(num_shifted>>1)&1;//取第1位c_new=num_shifted&1;//取第0位但是,注意:左移后,最低位补的是0,且我们只取低三位。那么上面的拆分方法就是取移位后的第2、1、0位。但是,如果移位前是3位,左移一位后变成4位,我们只取低三位,相当于对移位后的取模8(因为三位二进制最大为111,即7),所以也可以用取模来限制在3位:num_shifted%=8;//这样只保留低3位不过直接使用移位和按位与也可以,而且更直接。另外,考虑边界情况:当a=1,b=1,c=1时,合并后为111(7),左移一位后为14(二进制1110),取低三位为110(6),拆分为a_new=1,b_new=1,c_new=0。所以,我们可以这样写代码:步骤:1.合并:num=(a<<2)|(b<<1)|c;2.左移:num_shifted=num<<1;3.取低三位:num_shifted=num_shifted&0x07;//或者不单独写这一步,在拆分的时候直接取低三位(因为我们拆三位都是分别移位然后与1)实际上,我们拆的时候只取每个位上的一个比特位,所以即使左移后超过三位,我们只取最低三位。4.重新分配:a_new=(num_shifted>>2)&1;b_new=(num_shifted>>1)&1;c_new=(num_shifted)&1;注意:因为移位操作后,原来的变量a,b,c不再使用,我们需要用新的变量存储移位后的结果。下面是一个完整的例子:假设初始a=1,b=0,c=1合并:num=(1<<2)|(0<<1)|1=4|0|1=5(二进制101)左移:num_shifted=5<<1=10(二进制1010)然后取10的二进制低三位:010(因为1010的低三位是010)->十进制2拆分:a_new=(10>>2)&1->(1010右移2位变成10,即2)->2&1=0b_new=(10>>1)&1->(1010右移1位变成101,即5)->5&1=1c_new=10&1->0但这样拆分后是:0,1,0即010,这样我们就完成了左移并重新分配。然而,我们重新分配的结果应该是:原的每位左移后,新的a_new是原来b的值,b_new是原来c的值,c_new为0(因为左移后最低位补0)。在这个例子中,原来a=1,b=0,c=1,左移后:原本的a(最高位)被移出,剩下的部分是原来b(0)和c(1)向左移动一位(即原来的b变到了最高位,c变到了中间位,最低位补0),所以新的三个位应该是:b,c,0->0,1,0->所以a_new=0,b_new=1,c_new=0。上面的拆分结果是对的。但是注意:我们的拆分步骤:a_new对应的是移位后新的最高位(即第2位),c_new对应的是最低位(第0位)。但是,我们也可以这样理解左移操作:将三个看成一个整体,左移一位后,原来的最高位移出,第二高位变成了新的最高位,最低位变成了次低位,然后在最低位补0。所以用代码实现:注意:变量a,b,c的类型可以是unsignedint,但我们只使用0或1,所以也可以使用其他整数类型,但确保移位操作不会因为符号位出现问题(因为引用[3]中提到了signed类型移位会补符号位)。所以使用无符号更安全。因此,代码如下(假设a,b,c是已知的):unsignedinta,b,c;unsignedintnum,num_shifted;unsignedinta_new,b_new,c_new;//合并num=(a<<2)|(b<<1)|c;//左移一位num_shifted=num<<1;//重新分配,取低三位(因为左移后最多4位,我们只取最低三位)a_new=(num_shifted>>2)&1;b_new=(num_shifted>>1)&1;c_new=num_shifted&1;注意:这里我们并没有对左移后的进行取模(num_shifted%=8;),因为直接拆分时,即使num_shifted大于7,我们取最低三位也是用移位和与操作。但如果我们想确保只处理低三位,可以按位与0x07,即:num_shifted=(num<<1)&0x07;//只保留最低3位然后拆分:a_new=(num_shifted>>2)&1;b_new=(num_shifted>>1)&1;c_new=num_shifted&1;两种方式都可以。现在,我们来用例子验证:初始:a=1,b=1,c=1合并:num=(1<<2)|(1<<1)|1=4|2|1=7(二进制111)左移:7<<1=14(二进制1110),然后与0x07(即二进制0111)按位与:1110&0111=0110(6)拆分:a_new=(6>>2)&1->(6的二进制是110,右移2位是1,1&1=1);b_new=(6>>1)&1->6右移1位是11(二进制),即3,3&1=1;c_new=6&1=0;所以得到:1,1,0->相当于原来的1,1,1左移后变成1,1,0(最高位移出1,最低位补0)正确。但也可以不用按位与0x07,因为拆分的移位操作不会受高位影响(因为我们每个只取1位):num_shifted=14(二进制1110)a_new=(14>>2)&1->14右移2位:0011(二进制),即3,3&1=1b_new=(14>>1)&1->14右移1位:0111,即7,7&1=1c_new=14&1=0所以还是1,1,0因此,代码可以写为:unsignedinta,b,c;unsignedintnum=(a<<2)|(b<<1)|c;unsignedintshifted=num<<1;//重新拆分成三个变量a=(shifted>>2)&1;//如果a,b,c变量需要重新赋值,可以直接用b=(shifted>>1)&1;c=shifted&1;但是注意:重新赋值时,如果按顺序,在给a赋值前,原来的a值还在,但计算b的时候已经用了新的a值?不对,这里我们是用原来的a,b,c计算出合并后的,然后移位后重新赋值给a,b,c,所以应该这样:unsignedinta,b,c;//假设初始值已知unsignedintnum=(a<<2)|(b<<1)|c;num<<=1;//左移一位//然后重新赋值给a,b,ca=(num>>2)&1;b=(num>>1)&1;c=num&1;这样就可以一步完成。所以,完整代码示例:#include<stdio.h>intmain(){unsignedinta=1,b=0,c=1;//初始值:1,0,1printf("Beforeshift:a=%u,b=%u,c=%u\n",a,b,c);//合并并左移unsignedintnum=(a<<2)|(b<<1)|c;num<<=1;//左移一位//重新分配a=(num>>2)&1;b=(num>>1)&1;c=num&1;printf("Aftershift:a=%u,b=%u,c=%u\n",a,b,c);return0;}输出:Beforeshift:a=1,b=0,c=1Aftershift:a=0,b=1,c=0(即010,十进制的2)这个结果符合预期。注意:当移位后,最高位(即原来的第二位)被左移后移出,所以新的a是原来b的值(0),新的b是原来c的值(1),新的c为0。所以,我们完成了题目要求。另外,如果不想使用中间变量num,也可以直接重新赋值,但要小心使用临时变量存储原始值(因为重新赋值顺序会覆盖原始值),但是我们可以先计算出新值再一起赋值:如果不想用num,可以这样://使用临时变量存储原始值unsignedintold_a=a;unsignedintold_b=b;unsignedintold_c=c;//然后合并和移位后重新赋值a=((((old_a<<2)|(old_b<<1)|old_c)<<1)>>2)&1;//这样很麻烦,不如用中间变量清晰。或者用表达式一步完成:a=(((old_a<<2)|(old_b<<1)|old_c)<<1)>>2&1;b=(((old_a<<2)|(old_b<<1)|old_c)<<1)>>1&1;c=(((old_a<<2)|(old_b<<1)|old_c)<<1)&1;这样写重复计算很多,效率低,而且代码不清晰。所以,使用中间变量是清晰易读的。还有一种方法:利用位运算的特性,重新分配可以通过移位直接完成,而不通过合并为一个整数(这需要一点技巧):我们想达到的效果:把三个位看成一个整体左移一位,然后重新赋值给三个变量(原来的最高位移出,剩下的依次左移,最低位补0)。所以,实际上:新的a应该是原b的值;新的b应该是原c的值;新的c应该是0。所以可以直接:a_new=b;b_new=c;c_new=0;但是,这样做的效果和上面方法一样吗?注意:上面我们通过合并、移位、拆分得到了同样的结果。所以直接这样赋值也是可以的。但是,题目要求:合并为三位二进制后左移一位,再重新分配。直接赋值似乎绕开了中间过程,但得到相同结果。那么为什么我们不直接这样做?原因可能是,如果我们要实现的不仅仅是左移一位,而是左移任意位(例如左移2位)或者更复杂的操作,那么直接赋值就不够通用。但左移一位时,确实可以这样简化。所以,如果仅仅是左移一位,我们可以:a=b;b=c;c=0;但是,如果我们希望代码具有一般性(比如以后可能要改成左移2位,或者做其他移位操作),则使用合并、移位、拆分的方法更通用。因此,根据需求选择。如果题目要求就是左移一位,那么直接赋值更简单;如果要求合并为二进制后做任意位移操作,则用位运算的方法。题目要求:合并三个二进制为三位二进制,左移一位,重新分配三个变量。所以两种方法都可以,这里我们按照题目要求使用位运算的方法,以展示位操作过程。但如果要求代码简洁,也可以直接使用变量交换。然而,从问题描述看,用户要求通过合并、移位、重新分配的过程,所以我们应该使用位运算的完整过程。总结:通过位运算合并三个二进制为一个整数(3位),然后左移一位(变成4位,但我们只关心低3位),再拆分成三个二进制。因此,代码实现如上。另外,参考用户提供的引用[5],其中使用了位运算提取奇偶数位然后交换,我们这里的操作也是类似,通过移位和按位与来提取特定位。所以,我们提供上述位运算方法的代码。</think> 在C语言中,若要将三个独立存储的**单比特二进制**(每个变量存储0或1)合并为一个三位二进制,执行左移操作,然后重新分配给三个变量,可通过以下步骤实现: ### 实现原理与步骤 1. **合并三个二进制** 将三个单比特变量(`a`、`b`、`c`)按**从高位到低位**(`a`为最高位,`c`为最低位)合并为一个整数: ```c unsigned int num = (a << 2) | (b << 1) | c; ``` *示例*:若 `a=1, b=0, c=1` → `num = (1 << 2) | (0 << 1) | 1 = 5`(二进制 `101`) 2. **左移一位操作** 将合并后的左移一位(低位补0): ```c num <<= 1; // 等价于 num = num << 1; ``` *示例*:`5 << 1 = 10`(二进制 `1010`,实际保留低三位 `010`) 3. **重新拆分为三个变量** 从移位后的结果中**提取低三位**,分配给新的变量: ```c a = (num >> 2) & 1; // 提取第2位(新的最高位) b = (num >> 1) & 1; // 提取第1位 c = num & 1; // 提取第0位(新的最低位) ``` *示例*: - `a = (10 >> 2) & 1 = (2) & 1 = 0` - `b = (10 >> 1) & 1 = (5) & 1 = 1` - `c = 10 & 1 = 0` → 结果为 `a=0, b=1, c=0` --- ### 完整代码示例 ```c #include <stdio.h> int main() { unsigned int a = 1, b = 0, c = 1; // 初始值:a=1, b=0, c=1 printf("初始值: a=%d, b=%d, c=%d\n", a, b, c); // 1. 合并为三位二进制 unsigned int num = (a << 2) | (b << 1) | c; printf("合并结果: %d (二进制: %03b)\n", num, num); // 2. 左移一位 num <<= 1; printf("左移一位: %d (二进制: %04b)\n", num, num); // 3. 重新拆分给三个变量(保留低三位) a = (num >> 2) & 1; b = (num >> 1) & 1; c = num & 1; printf("重新分配: a=%d, b=%d, c=%d\n", a, b, c); return 0; } ``` ### 输出结果 ``` 初始值: a=1, b=0, c=1 合并结果: 5 (二进制: 101) 左移一位: 10 (二进制: 1010) 重新分配: a=0, b=1, c=0 ``` ### 关键点说明 1. **位操作原理**: - `<<`:左移操作,低位补0 - `>>`:右移操作,高位补0(需确保使用无符号类型,避免符号位问题) - `& 1`:屏蔽其他位,仅保留最低位值 2. **边界处理**: 左移后若产生进位(如输入 `1,1,1` 左移后为 `1110`),代码自动保留低三位(`110`),确保结果仍为三位二进制。 3. **安全建议**: - 变量使用 `unsigned int` 避免符号位干扰[^3] - 移位操作隐含对 $2^3=8$ 取模(保留低三位),无需显式取模运算[^5] --- ### 相关问题 1. 如何实现三位二进制的**右移**操作(高位补0)? 2. 如果每个变量存储的是**多比特二进制**(如4位),如何合并、移位、拆分? 3. 如何用C语言实现二进制的**循环左移**(最高位移到最低位)?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值