C语言判断一个数是否是2的幂次方或4的幂次方_C 语言

快速判断一个数是否是2的幂次方,若是,并判断出来是多少次方!
将2的幂次方写成二进制形式后,很容易就会发现有一个特点:二进制中只有一个1,并且1后面跟了n个0; 因此问题可以转化为判断1后面是否跟了n个0就可以了。

如果将这个数减去1后会发现,仅有的那个1会变为0,而原来的那n个0会变为1;因此将原来的数与去减去1后的数字进行与运算后会发现为零。

最快速的方法:

   (number & number - 1) == 0

原因:因为2的N次方换算是二进制为10……0这样的形式(0除外)。与上自己-1的位数,这们得到结果为0。例如。8的二进制为1000;8-1=7,7的二进制为111。两者相与的结果为0。计算如下:

     1000
   & 0111
    -------
    0000

使用递归来实现的代码如下:

#include "stdio.h"
#include "stdlib.h" 

int log2(int value)  //递归判断一个数是2的多少次方
{
  if (value == 1)
    return 0;
  else
    return 1+log2(value>>1);
} 

int main(void)
{
  int num;
  printf("请输入一个整数:");
  scanf("%d",&num);
  if(num&(num-1)) //使用与运算判断一个数是否是2的幂次方
    printf("%d不是2的幂次方!\n",num);
  else
    printf("%d是2的%d次方!\n",num,log2(num));
  system("pause");
  return 0;
}

使用非递归来实现的代码如下:

#include "stdio.h"
#include "stdlib.h" 

int log2(int value)  //非递归判断一个数是2的多少次方
{
  int x=0;
  while(value>1)
  {
    value>>=1;
    x++;
  }
  return x;
} 

int main(void)
{
  int num;
  printf("请输入一个整数:");
  scanf("%d",&num);
  if(num&(num-1))   //使用与运算判断一个数是否是2的幂次方
    printf("%d不是2的幂次方!\n",num);
  else
    printf("%d是2的%d次方!\n",num,log2(num));
  system("pause");
  return 0;
}

扩展:求一个数n的二进制中1的个数。
非常巧妙地利用了一个性质,n=n&(n-1) 能移除掉n的二进制中最右边的1的性质,循环移除,直到将1全部移除,这种方法将问题的复杂度降低到只和1的个数有关系。代码如下:

int Func3(int data)
{  //利用了data&(data-1)每次都能移除最右边的1,移除了多少个1,就是包含了几个1
  int count = 0;
  while (data)
  {
    data = data & (data-1);
    count++;
  }
  return count;
}

扩展问题二:

A和B的二进制中有多少位不相同。这个问题可以分为两步,(1)将A和B异或得到C,即C=A^B,(2)计算C的二进制中有多少个1。


快速判断一个数是否是4的幂次方,若是,并判断出来是多少次方!
将4的幂次方写成二进制形式后,很容易就会发现有一个特点:二进制中只有一个1(1在奇数位置),并且1后面跟了偶数个0; 因此问题可以转化为判断1后面是否跟了偶数个0就可以了。

4的整数次幂的二进制数都为 (4)100、(16)10000、(64)1000000......

另外,4的幂次方4^n也可以写为2^(2*n),即也可以写为2的幂次方,当然就满足2的幂次方的条件了,即num & num-1==0。

思路:首先用条件num & num-1==0来判断是否为2的幂次方,若不满足,则不是。若满足,在用条件num & 0x55555555来判断,若为真,则这个整数是4的幂次方,否则不是。

使用递归来实现的代码如下:

#include "stdio.h"
#include "stdlib.h" 

bool fn(unsigned int x)   //判断x是否是4的幂次方
{
 if ( x & (x - 1) )     //判断x是否为2的幂次方
   return false;
 return x & 0x55555555;   //判断1是否在奇数位置上
} 

int log4(int value)   //递归判断一个数是4的多少次方
{
  if (value == 1)
    return 0;
  else
  {
    value>>=1;    //往右移位
    return 1+log4(value>>1);    //往右移位
  }
} 

int main(void)
{
  int num;
  printf("请输入一个整数:");
  scanf("%d",&num);
  if(fn(num))   //使用与运算判断一个数是否是2的幂次方
    printf("%d是4的%d次方!\n",num,log4(num));
  else
    printf("%d不是4的幂次方!\n",num);
  system("pause");
  return 0;
} 

使用非递归来实现的代码如下:

#include "stdio.h"
#include "stdlib.h" 

bool fn(unsigned int x)   //判断x是否是4的幂次方
{
 if ( x & (x - 1) )     //判断x是否为2的幂次方
   return false;
 return x & 0x55555555;   //判断1是否在奇数位置上
} 

int log4(int value)  //非递归判断一个数是4的多少次方
{
  int x=0;
  while(value>1)
  {
    value>>=1;   //往右移位
    value>>=1;
    x++;
  }
  return x;
}  

int main(void)
{
  int num;
  printf("请输入一个整数:");
  scanf("%d",&num);
  if(fn(num))   //使用与运算判断一个数是否是2的幂次方
    printf("%d是4的%d次方!\n",num,log4(num));
  else
    printf("%d不是4的幂次方!\n",num);
  system("pause");
  return 0;
} 

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索c语言
幂次方
c语言幂次方、c语言 幂次方编程、c语言10的n次方、c语言2的n次方、c语言次方,以便于您获取更多的相关知识。

时间: 2024-10-27 03:26:54

C语言判断一个数是否是2的幂次方或4的幂次方_C 语言的相关文章

C语言实现带头结点的链表的创建、查找、插入、删除操作_C 语言

本文实例讲述了C语言实现带头结点的链表的创建.查找.插入.删除操作.是数据结构中链表部分的基础操作.分享给大家供大家参考.具体方法如下: #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node* next;// 这个地方注意结构体变量的定义规则 } Node, *PNode; Node* createLinklist(int length) { int i = 0; PNo

C语言编程中对目录进行基本的打开关闭和读取操作详解_C 语言

C语言opendir()函数:打开目录函数头文件: #include <sys/types.h> #include <dirent.h> 定义函数: DIR * opendir(const char * name); 函数说明:opendir()用来打开参数name 指定的目录, 并返回DIR*形态的目录流, 和open()类似, 接下来对目录的读取和搜索都要使用此返回值. 返回值:成功则返回DIR* 型态的目录流, 打开失败则返回NULL. 错误代码: 1.EACCESS 权限不

C语言中结构体偏移及结构体成员变量访问方式的问题讨论_C 语言

c语言结构体偏移 示例1 我们先来定义一下需求: 已知结构体类型定义如下: struct node_t{ char a; int b; int c; }; 且结构体1Byte对齐 #pragma pack(1) 求: 结构体struct node_t中成员变量c的偏移. 注:这里的偏移量指的是相对于结构体起始位置的偏移量. 看到这个问题的时候,我相信不同的人脑中浮现的解决方法可能会有所差异,下面我们分析以下几种可能的解法: 方法1 如果你对c语言的库函数比较熟悉的话,那么你第一个想到的肯定是of

C语言的fork函数在Linux中的进程操作及相关面试题讲解_C 语言

fork的意义 下图为,C 程序的存储空间布局(典型) 1.一个现有进程可以调用 fork 函数创建一个新进程. 2.fork 函数被调用一次,但返回两次, 两次返回的唯一区别是子进程的返回值是 0, 而父进程的返回值是新子进程的 PID. 3.子进程和父进程继续执行 fork 调用之后的指令. 在上图的存储空间布局中,父子进程只共享正文段,其余的都各自有独立的副本 (通常使用 copy-on-write 的策略,速度比较快). fork 的两种用法 1.父子进程同时执行不同的代码段典型应用:W

C++快速幂与大数取模算法示例_C 语言

一.快速幂 其实就是求(a^b)% p ,(其中a,b,p都比较大在int范围内)这类问题. 首先要知道取余的公式: (a*b)%p=(a%p*b%p)%p . 那么幂不就是乘机的累积吗,由此给出代码: int fast(int a,int b,int p) { long long a1=a,t=1; while(b>0) { if(b&1) /如果幂b是奇数多乘一次,因为后边会除2变偶数,(7/2=3) t=(t%p)*(a1%p)%p; a1=(a1%p)*(a1%p)%p; b/=2;

使用C语言递归与非递归实现字符串反转函数char *reverse(char *str)的方法_C 语言

代码如下所示: 复制代码 代码如下: // 递归实现字符串反转   char *reverse(char *str)   {    if( !str )    {     return NULL; }       int len = strlen(str);       if( len > 1 )       {           char ctemp =str[0];           str[0] = str[len-1];              str[len-1] = '/0';

C语言中多维数组的内存分配和释放(malloc与free)的方法_C 语言

如果要给二维数组(m*n)分配空间,代码可以写成下面: 复制代码 代码如下: char **a, i; // 先分配m个指针单元,注意是指针单元 // 所以每个单元的大小是sizeof(char *) a = (char **) malloc(m * sizeof(char * )); // 再分配n个字符单元, // 上面的m个指针单元指向这n个字符单元首地址 for(i = 0; i < m; i++) a[i] = (char * )malloc(n * sizeof(char )); 释

C语言中判断一个数是否是回文数

注:回文数即数字顺着和反着是同一个数! 看了郝斌老师的C语言视频,虽然还只看了80多个,但是还是有一些体会,编程应该养成良好的编程风格,至少到现 在为止写的这些小程序都应该有下面这样一个过程: 1,流程:(知道程序是按照怎样的顺序运行的) 2,功能:(理解程序的作用) 3,试数:(我个人简单的理解为测试过程,把自己当作计算机去执行程序) /* 2012年4月20日 10:36:23 判断一个数是否是回文数 */ #include <stdio.h> int main(void) { int v

c语言-C语言中如何判断一个数是否为周期数字,如:123123,12341234,123123123

问题描述 C语言中如何判断一个数是否为周期数字,如:123123,12341234,123123123 C语言中如何判断一个数是否为周期数字,如:123123,12341234,123123123 解决方案 转换成字符串,用最长公共子串(LCS)算法. 解决方案二: 可以证明的是,一个周期循环的字符串,必然它的周期是最长公共子串.有了周期,从头开始逐一比较每一段是不是这个串就可以了. 解决方案三: 最长公共子串(LCS) 解决方案四: 没有现成的函数给你用,所以要自己想办法写程序来实现. 解决方