C语言学习笔记20260607-判断一个数是否为2的n次方(三种方法)
一、题目说明
输入一个正整数,判断该数是否为 2 的整数次方。
如果是:输出 数值 = 2^次方数
如果不是:输出该数不是2的整数次幂
附加功能:输入容错处理(负数、字母、非法数据自动重输)
二、2的次方数学特征
2的整数次幂序列:1、2、4、8、16、32、64......
特征:
-
不断除以2,最终结果一定是 1
-
二进制中 有且仅有一个 1
-
位运算公式:
(n & (n - 1)) == 0
方法一:暴力乘2法(从1累乘2)
1. 思路
从 1(2^0) 开始不断乘2,不断逼近输入的数字:
-
累乘结果 == 输入数 → 是2的次方
-
累乘结果 > 输入数 → 不是2的次方
2. 完整代码
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
// 方法1:暴力乘2法
int main()
{
int num;
printf("请输入一个正整数:\n");
// 输入容错:非数字、负数、0 全部重输
while (scanf("%d", &num) != 1 || num <= 0)
{
printf("输入无效!请输入正整数:\n");
while (getchar() != '\n'); // 清空缓冲区脏数据
}
int i = 1; // 初始值 2^0 = 1
int cnt = 0; // 记录次方数
while (1)
{
if (num > i)
{
i *= 2; // 继续乘2
cnt++; // 次方数+1
}
else if (i == num)
{
// 刚好相等,说明是2的cnt次方
printf("%d = 2^%d\n", num, cnt);
break;
}
else
{
// 累乘结果超过原数,不可能相等
printf("%d 不是2的整数次幂\n", num);
break;
}
}
return 0;
}
3. 优缺点
-
逻辑最直白、新手最好理解
-
循环次数多,效率一般
方法二:暴力除2法
1. 思路
如果一个数是2的整数次幂,反复除以2后,最终一定等于1。
中途一旦出现不能整除 → 一定不是2的次方。
2. 完整代码
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
// 方法2:暴力除2法
int main()
{
int n;
printf("输入正整数:");
// 输入容错
while (scanf("%d", &n) != 1 || n <= 0)
{
printf("非法输入,重输:");
while (getchar() != '\n');
}
int temp = n;
int k = 0; // 记录次方
// 能被2整除就一直除
while (temp % 2 == 0)
{
temp /= 2;
k++;
}
// 除到最后为1,说明是2的次方
if (temp == 1)
printf("%d = 2^%d\n", n, k);
else
printf("%d 非2的次幂\n", n);
return 0;
}
3. 优缺点
-
代码简短、逻辑清晰、考试首选
-
效率高、极易背诵
方法三:位运算判断法
1. 核心原理
2的整数次幂,二进制 只有一个1。
n & (n - 1) 可以消去唯一的1
结果为0 → 是2的次方
结果不为0 → 不是2的次方
2. 完整代码
c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
// 方法3:位运算快速判断法
int main()
{
int n, cnt = 0;
printf("输入正整数:");
// 输入容错
while (scanf("%d", &n) != 1 || n <= 0)
{
printf("非法输入,重输:");
while (getchar() != '\n');
}
// 位运算核心判断
if ((n & (n - 1)) != 0)
{
printf("%d 不是2的次幂", n);
return 0;
}
// 计算具体是2的多少次方
while ((1 << cnt) != n)
{
cnt++;
}
printf("%d = 2^%d", n, cnt);
return 0;
}
3. 优缺点
-
运算速度最快,底层最优解法
-
需要掌握二进制位运算知识