怎样用c语言定义高幂整数,位操作运算的奇技淫巧!(附源码)

位运算

百度百科如下:

程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作

位操作的优势

位运算是一种底层的运算,往往比我们普通的运算要快上许多许多

位运算是最高效而且占用内存最少的算法操作,执行效率非常高

位运算操作的是二进制数,会拥有一些二进制的特性,在实际问题可以方便运用

位运算只需较低的空间需求

位运算使用能使程序变得更加简洁和优美

位运算可以表示一些状态集合

运算符号

下面的a和b都是整数类型,则:

含义

C语言

按位与

a & b

按位或

a | b

按位异或

a ^ b

按位取反

~a

左移

a << b

带符号右移

a >> b

无符号右移

优先级

C语言中位运算符之间,按优先级顺序排列为

优先级

符号

1

~

2

<>

3

&

4

^

5

|

6

&=、^=、|=、<<=、>>=

概念简介以及技巧

本文会以C语言的交互环境来做代码演示

常见的二进制位的变换操作

5aafSjQNKwiTCUp5rhu7GexjRlnf8tpdDUOrWIbzalaFKxy7UOzfSh2nOsvxFOqp7HIlqpoJ8ZqzTVRiTns4PYKTx6VIFse0ADw

and运算 &

判断奇偶数

对于除0以外的任意数x,使用x&1==1作为逻辑判断即可

if (x&1==1)

{

}

判断某个二进制位是否为1

比如第7位, 0x40转到二进制是0100 0000,代表第7位是1.

if (n&0x40)

{

//TODO:添加你要处理的代码

}

字节读取

(x >> 0) & 0x000000ff/* 获取第0个字节 */

(x >> 8) & 0x000000ff/* 获取第1个字节 */

(x >> 16) & 0x000000ff/* 获取第2个字节 */

(x >> 24) & 0x000000ff/* 获取第3个字节 */

判断一个数是不是 22 的指数

bool isPowerOfTwo(int n) {

if (n <= 0) return false;

return (n & (n - 1)) == 0;

}

取余

//得到余数

int Yu(int num,int n)

{

int i = 1 << n;

return num&(i-1);

}

指定二进制位数截取

比如说16位二进制数A:1001 1001 1001 1000,如果来你想获A的哪一位的值,就把数字B:0000 0000 0000 0000的那一位设置为1.

比如说我想获得A的第三位就把B的第三位数字设置为1,则B为0000 0000 0000 0100,设置完之后再把A、B求与, 其结果若为0,说明A的第三位为0,其结果为1,说明A的第三位为1.

同理:若要获得A的第五位,就把B设置为0000 0000 0001 0000,之后再求与。

通常在我们的程序中,数字B被称为掩码,其含义是专门用来测试某一位是否为0的数值。

统计二进制中 1 的个数

利用x=x&(x-1),会将x用二进制表示时最右边的一个1变为0,因为x-1会将该位变为0.

int Count(int x)

{ int sum=0;

while(x)

{ sum++;

x=x&(x-1);

}

return sum;

}

or操作

生成组合编码,进行状态压缩

当把二进制当作集合使用时,可以用or操作来增加元素。合并编码 在对字节码进行加密时,加密后的两段bit需要重新合并成一个字节,这时就需要使用or操作。

求一个数的二进制表达中0的个数

int Grial(int x)

{

int count = 0;

while (x + 1)

{

count++;

x |= (x + 1);

}

return count;

}

xor操作

两个整数交换变量名

void swap(int &a, int &b) {

a ^= b;

b ^= a;

a ^= b;

}

判断两个数是否异号

int x = -1, y = 2;

bool f = ((x ^ y) < 0); // true

int x = 3, y = 2;

bool f = ((x ^ y) < 0); // false

数据加密

将需要加密的内容看做A,密钥看做B,A ^ B=加密后的内容C。而解密时只需要将C ^ 密钥B=原内容A。如果没有密钥,就不能解密!

#include

#include

#include

#define KEY 0x86

int main()

{

char p_data[16] = {"Hello World!"};

char Encrypt[16]={0},Decode[16]={0};

int i;

for(i = 0; i < strlen(p_data); i++)

{

Encrypt[i] = p_data[i] ^ KEY;

}

for(i = 0; i < strlen(Encrypt); i++)

{

Decode[i] = Encrypt[i] ^ KEY;

}

printf("Initial date: %s\n",p_data);

printf("Encrypt date: %s\n",Encrypt);

printf("Decode date: %s\n",Decode);

return 0;

}

数字判重

利用了二进制数的性质:x^y^y = x。我们可见,当同一个数累计进行两次xor操作,相当于自行抵销了,剩下的就是不重复的数

找出没有重复的数

int find(int[] arr){

int tmp = arr[0];

for(int i = 1;i < arr.length; i++){

tmp = tmp ^ arr[i];

}

return tmp;

}

not操作

交换符号

int reversal(int a) {

return ~a + 1;

}

取绝对值(效率高)

n>>31 取得n的符号

若n为正数,n>>31等于0

若n为负数,n>>31等于-1

若n为正数 n^0=0,数不变

若n为负数,有n^-1 需要计算n和-1的补码,然后进行异或运算,结果n变符号并且为n的绝对值减1,再减去-1就是绝对值

int abs(int n)

{

return (n ^ (n >> 31)) - (n >> 31);

}

也可以这样使用

int abs(int n)

{

int i = n >> 31;

return i == 0 ? n : (~n + 1);

}

从低位到高位.将n的第m位置1

将1左移m-1位找到第m位,得到000...1...000, n在和这个数做或运算

int setBitToOne(int n, int m)

{

return n | (1 << (m-1));

}

同理从低位到高位,将n的第m位置0,代码如下

int setBitToZero(int n, int m)

{

return n & ~(1 << (m-1));

}

shl操作 & shr操作

求2的N次方

1<

高低位交换

unsigned short a = 34520;

a = (a >> 8) | (a << 8);

进行二进制逆序

unsigned short a = 34520;

a = ((a & 0xAAAA) >> 1) | ((a & 0x5555) << 1);

a = ((a & 0xCCCC) >> 2) | ((a & 0x3333) << 2);

a = ((a & 0xF0F0) >> 4) | ((a & 0x0F0F) << 4);

a = ((a & 0xFF00) >> 8) | ((a & 0x00FF) << 8);

获得int型最大最小值

int getMaxInt()

{

return (1 << 31) - 1;//2147483647, 由于优先级关系,括号不可省略

}

int getMinInt()

{

return 1 << 31;//-2147483648

}

m的n次方

//自己重写的pow()方法

int pow(int m , int n){

int sum = 1;

while(n != 0){

if(n & 1 == 1){

sum *= m;

}

m *= m;

n = n >> 1;

}

return sum;

}

找出不大于N的最大的2的幂指数

int findN(int n){

n |= n >> 1;

n |= n >> 2;

n |= n >> 4;

n |= n >> 8 // 整型一般是 32 位,上面我是假设 8 位。

return (n + 1) >> 1;

}

二分查找32位整数的前导0个数

int nlz(unsigned x)

{

int n;

if (x == 0) return(32);

n = 1;

if ((x >> 16) == 0) {n = n +16; x = x <<16;}

if ((x >> 24) == 0) {n = n + 8; x = x << 8;}

if ((x >> 28) == 0) {n = n + 4; x = x << 4;}

if ((x >> 30) == 0) {n = n + 2; x = x << 2;}

n = n - (x >> 31);

return n;

}

位图的操作

将 x 的第 n 位置1,可以通过 x |= (x << n) 来实现

set_bit(char x, int n);

将 x 的第 n 位清0,可以通过 x &= ~(1 << n) 来实现

clr_bit(char x, int n);

取出 x 的第 n 位的值,可以通过 (x >> n) & 1 来实现

get_bit(char x, int n);

如下:

#define clr_bit(x, n) ( (x) &= ~(1 << (n)) )

#define set_bit(x, n) ( (x) |= (1 << (n)) )

#define get_bit(x, n) ( ((x)>>(n)) & 1 )

综合应用

以下仅列出,感兴趣可以参考下面链接.

关于操作计数方法

计算整数的符号

检测两个整数是否具有相反的符号

计算无分支的整数绝对值(abs)

计算两个整数的最小值(最小值)或最大值(最大值),而无需分支

确定整数是否为2的幂

标志延伸

从恒定位宽扩展的符号

从可变位宽扩展的符号

通过3个操作从可变位宽扩展符号 有条件地设置或清除位而不分支

有条件地否定一个值而不分支

根据掩码合并两个值中的位

计数位设置

计数位设置,幼稚的方式

计算由查找表设置的位

数位集,Brian Kernighan的方式

使用64位指令对14、24或32位字中设置的位进行计数

并行设置计数位

从最高有效位到给定位置的计数位的设置(等级)

从给定的计数(等级)中选择位位置(从最高有效位开始)

计算奇偶校验(如果设置了奇数位数,则为1,否则为0)

天真地计算单词的奇偶性

通过查找表计算奇偶校验

使用64位乘法和模数除法计算字节的奇偶校验

用乘法计算单词的奇偶校验

并行计算奇偶校验

交换价值

用减法和加法交换值

用XOR交换值

用XOR交换单个位

反转位序列

反转位是显而易见的方式

逐字查找表中的位反转

通过3个操作(64位乘法和模数除法)反转字节中的位

通过4个操作反转字节中的位(64位乘法,无除法)

通过7个操作反转字节中的位(无64位,仅32位)

与5 * lg(N)个运算并行地反转N位数量

模数除法(又名计算余数)

在不进行除法运算的情况下,将模数除以1 << s(显而易见)

在不进行除法运算的情况下以(1 << s)-1计算模数除法

不进行除法运算就并行计算(1 << s)-1的模数除法

查找整数的整数对数2(又称最高位集的位置)

使用O(N)运算找到MSB N设置为整数的对数2(显而易见的方法)

查找具有64位IEEE浮点数的整数的整数对数2

使用查找表找到整数的对数2

在O(lg(N))运算中找到N位整数的对数2

使用乘法和查找在O(lg(N))操作中找到N位整数的对数2

查找整数的对数以10为底的整数

查找整数的整数对数10

查找32位IEEE浮点数的整数对数基数2

查找32位IEEE浮点的pow(2,r)根的整数对数基数2(对于无符号整数r)

计算连续的尾随零位(或查找位索引)

线性计算右边的连续零位(后缀)

并行计算右侧连续的零位(后缀)

通过二进制搜索计算右边连续的零位(跟踪)

通过强制转换为浮点数来计算右侧连续的零位(跟踪)

用模数除法和查找计算右边连续的零位(跟踪)

用乘法和查找计数右边连续的零位(后跟)

通过浮法舍入到2的下一个最高幂

向上舍入到2的下一个最高幂

交织位(也称为计算莫顿数)

交错位的明显方式

通过表查找交织位

带64位乘法的交织位

通过二进制幻数交错位

测试单词中的字节范围(并计算出现的次数)

确定单词是否为零字节

确定一个单词的字节数是否等于n

确定一个单词的字节数是否小于n

确定单词的字节数是否大于n

确定单词是否在m和n之间有一个字节

按词典顺序计算下一位排列

更多内容可以查看:

http://graphics.stanford.edu/~seander/bithacks.html

本文授权转载自公众号“技术让梦想更伟大”,作者李肖遥

-END-

免责声明:整理文章为传播相关技术,版权归原作者所有,如有侵权,请联系删除

6bWPR3ZeaHSbSa0zwhpUDB3+FFgV3VlWMJT4hgHsNx0cMeoFsNtLLkzYawJat8+duF+InZJp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/398913.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android系统耗电量大待机,安卓手机耗电快有什么解决办法吗 安卓手机待机耗电量大怎么办...

虽然手机发展速度越来越快&#xff0c;技术也越来越高了&#xff0c;电池容量相对之前的900毫安1000毫安&#xff0c;都上升到了2000毫安到5000毫安&#xff0c;但是感觉待机的时间和正常的使用时间&#xff0c;却没有之前那么长了&#xff0c;难道手机电池容量是假的&#xff…

js 中null,undefined区别

首先摘自阮一峰先生的文章&#xff1a; 大多数计算机语言&#xff0c;有且仅有一个表示"无"的值&#xff0c;比如&#xff0c;C语言的NULL&#xff0c;Java语言的null&#xff0c;Python语言的None&#xff0c;Ruby语言的nil。 有点奇怪的是&#xff0c;JavaScript语…

六款值得推荐的Android开源框架简介

六款值得推荐的Android开源框架简介 技术不再多&#xff0c;知道一些常用的、不错的就够了。下面就是最近整理的“性价比”比较高的Android开源框架&#xff0c;应该是相对实用的。 1、volley 项目地址 https://github.com/smanikandan14/Volley-demo JSON&#xff0c;图像等的…

数据库杂谈(一)——数据库基本概念

文章目录1 数据库基本概念1.1数据库和数据库管理系统1.2 数据库系统和文件系统1.3 数据模型1.4 数据库三级模式和两级独立性1.4.1 三级模式1.4.2 二级映像功能1.4.3 数据独立性1.5 数据库发展历史及分类1.6 数据库系统的组成和生命周期1.6.1 三个概念1.6.2 生命周期1.6.3 存储管…

【转】Java删除文件夹和文件

原文网址&#xff1a;http://kxjhlele.iteye.com/blog/323657 以前在javaeye看到过关于Java操作文件的一篇文章&#xff0c;写的很好&#xff0c;但找了半天也没找到&#xff0c;就把找到底几篇文章整理一下&#xff0c;做个总结&#xff0c;算是一个学习备份…… 1&#xff0c…

数据库杂谈(二)——数据模型

2 数据模型 摘要&#xff1a;数据模型&#xff08;Data Model&#xff09;是数据特征的抽象&#xff0c;它从抽象层次上描述了系统的静态特征、动态行为和约束条件&#xff0c;为数据库系统的信息表示与操作提供一个抽象的框架。数据模型所描述的内容有三部分&#xff0c;分别是…

android编译系统apk文件,VS2012中MonoForAndroid打包编译APK文件详细图文教程

本文用于介绍Visual Studio 2012中Xamarin Mono For Android 如何打包编译APK文件&#xff0c;从如何创建Android项目&#xff0c;到如何启动调试&#xff0c;都会逐个配图讲解。1 新建项目2 选择安卓3 选择安卓程序4 随便取名和设置存放路径5 确定1 创建完一个新的项目2 点击“…

判断程序是否已经运行

近段时间&#xff0c;需要写一个小功能&#xff0c;就是需要判断程序是否已经运行。某个程序安装后&#xff0c;也许被多个用户运行。那怎样判断当前用户已经运行了此程序了呢&#xff1f;下面是Insus.NET的做法&#xff0c;就是&#xff1a;《VB.NET WinForm获取运行程序用户名…

浅谈缓存技术在ASP.NET中的运用

本篇文章虽不谈架构&#xff0c;但是Cache又是架构中不可或缺的部分&#xff0c;因此&#xff0c;在讲解Cache的同时&#xff0c;将会提及到部分架构知识&#xff0c;关于架构部分&#xff0c;读者可以不用理解&#xff0c;或者直接跳过&#xff0c; 你只需关心Cache即可&#…

Git快速入门+复习笔记

对于学习编程的同志来说&#xff0c;学习Git是必不可少的一项技术&#xff0c;如果你是第一次观看我的文章&#xff0c;欢迎关注我的频道&#xff0c;我会分享更多有趣的知识。 文章目录1 目标2 概述2.1 开发中的实际场景2.2 版本控制器的方式2.3 工作流程图3 Git安装和常用命令…

Android浏览器速度测试,Android平台浏览器网页加载速度对比评测

参与测试的浏览器手机上网已经渐渐成为人们的一种习惯&#xff0c;无论在等公交时、乘地铁时、吃饭等餐时&#xff0c;很多朋友都习惯掏出手机简单浏览一下微博、人人、新闻网站等页面。移动网络的确为我们带来了莫大的便利&#xff0c;但网速和稳定性却是移动网络的硬伤。针对…

操作系统随笔(一)

你好朋友&#xff0c;当你点进来这份读书笔记时&#xff0c;我相信你不是无意中点进来就是对这一部分饶有兴趣&#xff0c;可惜的是&#xff0c;我也只是个普通的大学生&#xff0c;有时候对知识的见解获取没有屏幕前的你那么有天赋&#xff0c;所以在阅读完这篇文章的同时点个…

codeforces 483B Friends and Presents 解题报告

题目链接&#xff1a;http://codeforces.com/problemset/problem/483/B 题目意思&#xff1a;有两个 friends&#xff0c;需要将 cnt1 个不能整除 x 的数分给第一个friend&#xff0c;cnt2 个不能整除 y 的数分给第二个friend。x 和 y 都是素数来的。要求求出最小的 v&#xff…

并行计算随笔(一)

如果觉得本篇文章对你有所启发&#xff0c;请给我点个赞好吗&#xff0c;这对我很重要&#xff0c;谢谢 文章目录1 并行计算基础1.1 什么是并行计算1.1.1 对计算速度的需求1.1.2 并行计算1.1.3 并行计算的基本条件1.1.4 平行计算和分布式计算1.2 为什么需要并行计算1.3 并行计算…

命令行的形式运行php

转自&#xff1a;http://www.cnblogs.com/myjavawork/articles/1869205.html 注意&#xff1a;在安装php时需要将php 的安装目录加到环境变量 PATH 中 (右击我的电脑->属性->高级->环境变量, 如果存在 PATH 则在原来的 PATH 中加入你的PHP安装目录, 如果不存在则新建一…

idea android 模块,IntelliJ IDEA 12 - 新的Android应用程序模块向导失败,“无法找到模块的资源目录”...

我面临的问题是一个非常简单的问题... 我无法使用IntelliJ IDEA 12来帮助我创建一个Android应用程序模块(项目)。IntelliJ IDEA 12 - 新的Android应用程序模块向导失败&#xff0c;“无法找到模块的资源目录”成功安装的IntelliJ IDEA 12和使IDE和二者的SDK(Java和Android设备)…

JQuery常用知识点汇总

2019独角兽企业重金招聘Python工程师标准>>> 0、JQuery的基本属性标识&#xff1a; $(".xxx")&#xff1a;标签的class属性&#xff1b; $("#xxx")&#xff1a;标签的id属性&#xff1b; $("xxx")&#xff1a; 标签名&#…

数据库杂谈(三)——关系代数

3 形式化关系查询语言 摘要&#xff1a;关系代数是一种抽象的查询语言&#xff0c;用对关系的运算来表达查询&#xff0c;作为研究关系数据语言的数学工具。在本文中&#xff0c;我们不仅谈论关系代数的知识点&#xff0c;而且还配备了对应的练习题。 文章目录3 形式化关系查询…

android native.js,Android Native与JS通信互调

写在最前&#xff1a;看Android最新技术总结&#xff0c;关注公众号&#xff1a;最近因为App与H5交互逻辑太乱&#xff0c;所以抽空梳理了下&#xff1b;对目前App与H5的各种交互通信做个总结&#xff0c;自取适合自己的交互方式。一、H5调用原生的native方法1、拦截shouldOver…

SharePoint2013 Excel导出好的代码

C#Excel操作类ExcelHelper.cs 来源&#xff1a;http://www.hellocsharp.com/article/67.aspx C#源码世界 发布于&#xff1a; 2014-09-12使用本类之前必须在本机安装了office excel组件或直接下载Microsoft.Office.Interop.Excel.dll文件引用到项目目录下&#xff1a; 然后复制…