位运算

二进制-高效位运算

自古美人都是妖i 提交于 2020-03-08 10:11:44
数独 数独是介绍位运算的好例子,运用位运算和不运用效率差别还是挺大的。我们先看数独需求: 1、当前数字所在 行 数字均含1-9,不重复 2、当前数字所在 列 数字均含1-9,不重复 3、当前数字所在 宫 (即3x3的大格)数字均含1-9,不重复(宫,如下图每个粗线内是一个宫) 、 常规算法 若是我们采用常规方式的,每填写一个数字,需要检查当前行、列,宫中其他位置是否有重复数字,极端情况下需要循环27(3*9)次来进行检查,我们看下常规算法下check int check(int sp) { // 檢查同行、列、九宮格有沒有相同的數字,若有傳回 1 int fg= 0 ; if(!fg) fg= check1(sp, startH[sp], addH) ; // 檢查同列有沒有相同的數字 if(!fg) fg= check1(sp, startV[sp], addV) ; // 檢查同行有沒有相同的數字 if(!fg) fg= check1(sp, startB[sp], addB) ; // 檢查同九宮格有沒有相同的數字 return(fg) ; } int check1(int sp, int start, int *addnum) { // 檢查指定的行、列、九宮格有沒有相同的數字,若有傳回 1 int fg= 0, i, sp1 ; //万恶的for循环 for(i=0; i

C++ 的位运算:__builtin, bitset

风流意气都作罢 提交于 2020-03-08 10:07:54
int __builtin_ffs (unsigned int x) 返回二进制表示中 x 的最后一位 \(1\) (最右边的)是从后向前第几位,比如 \(7368(1110011001000)\) 返回 \(4\) 。 int __builtin_clz (unsigned int x) 返回二进制表示中前导 \(0\) 的个数。 int __builtin_ctz (unsigned int x) 返回二进制表示中末尾 \(0\) 的个数。 int __builtin_popcount (unsigned int x) 返回二进制表示中 \(1\) 的个数。 int __builtin_parity (unsigned int x) 返回 x 的奇偶校验位,也就是 x 的 \(1\) 的个数模 \(2\) 的结果。 这些函数都有相应的 unsigned long 和 unsigned long long 版本,只需在函数名后面加上 l 或 ll 即可,如 int __builtin_clzll bitset 定义在 <bitset> 库中。 bitset<8> b1; // [0,0,0,0,0,0,0,0] bitset<8> b2(42); // [0,0,1,0,1,0,1,0] bitset<17> bs(0xfff0); // [1,1,1,1,1,1,1,1,1,1

高效位运算 __builtin_系列函数

橙三吉。 提交于 2020-03-08 10:07:10
•int __builtin_ffs (unsigned int x) 返回x的最后一位1的是从后向前第几位,比如7368(1110011001000)返回4。 •int __builtin_clz (unsigned int x) 返回前导的0的个数。 •int __builtin_ctz (unsigned int x) 返回后面的0个个数,和__builtin_clz相对。 •int __builtin_popcount (unsigned int x) 返回二进制表示中1的个数。 •int __builtin_parity (unsigned int x) 返回x的奇偶校验位,也就是x的1的个数模2的结果。 此外,这些函数都有相应的usigned long和usigned long long版本,只需要在函数名后面加上l或ll就可以了,比如int __builtin_clzll。 来源: https://www.cnblogs.com/zxz666/p/11188763.html

位运算

断了今生、忘了曾经 提交于 2020-03-06 03:46:49
# 数值表示 1)补码表示:-n=~n+1 2)经验值数:0x3f3f3f3f。 不会溢出 用于最大值的定义 3)二进制数下标从0开始 4)返回n的最后一位1:lowbit(n) = n & -n # 移位操作 1)1<<n=2^n 2)n<<1=2n 3)算数右移 正数补0,负数补1 4)n>>1=[n/2.0](下取整) 5)b&1 取出b在二进制下表示的最低位 6)b>>1 舍去二进制下的最低位 7)(n>>k)&1 取出整数n在二进制表示下的第k位 8)n & ( (1<<k)-1) 取出整数在二进制表示下的第0~k-1位(后k位) 9)n xor (1<<k) 把整数 n 在二进制下表示的第k位取反 10)n | (1<<k) 把整数n在二进制表示下的第k位赋值1 11)n & (~(1<<k)) 对整数n在二进制表示下的第k位赋值0 来源: https://www.cnblogs.com/hhyx/p/12424326.html

[算法]位运算问题之二

一曲冷凌霜 提交于 2020-03-04 20:33:21
题目一: 给定一个整形数组arr和一个大于1的整数k。已知arr中只有1个数出现了奇数次,其他的数都出现了偶数次,请返回出现了奇数次的数。 时间复杂度为O(N),额外空间复杂度为O(1)。 思路: 整数n与0异或的结果是n,整数n与整数n异或的结果是0.所以先申请一个整形变量,记为eO。把eO和每个数异或(eO=eO^当前数),最后eO的值就是出现了奇数次的那个数。 异或运算满足交换律和结合律。 public static void printOddTimesNum1(int[] arr) { int eO = 0; for (int cur : arr) { eO ^= cur; } System.out.println(eO); } 题目二: 给定一个整形数组arr,有两个数出现了奇数次,其他数都出现了偶数次。打印这两个数。 思路: 如果只有a和b出现了奇数次,那么最后的异或结果eO一定是a^b。所以,如果数组中有两个出现了奇数次的数,最终的结果eO一定不为0.那么肯定能在32位整数eO上找到一个不等于0的bit位,假设是第K为不等于0。eO在第K位上不等于0,说明a和b的第k位肯定有一个是1另一个是0.接下来再设置一个变量记为eHasOne,然后再遍历一次数组。在这次遍历中,eHasOne只与第k位上是1的整数异或,其他的数被忽略。那么在第二次遍历结束后

不用加减乘除做加法

徘徊边缘 提交于 2020-03-04 19:13:07
题目 :写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。 分析:对数字做运算,最常用的就是四则运算和位运算了,这里要求不能使用四则运算,那么我们可以考虑位运算,可以用位运算来进行加法运算。首先,举两个例子: 例1. 12+13(1100+1101) 1100 ^ 1101 = 0001(对应位相加,不考虑进位) 1100 & 1101 = 1100(1代表产生进位的地方) 11000 ^ 00001 = 11001 = 25(进位左移一位,与不考虑进位时的结果相加,不考虑进位) 11000 & 0001 = 0(无进位,则上一步异或的结果为左后的结果) 例2. 15+6(1111+0110) 1111 ^ 0110 = 1001 1111 & 0110 = 0110 01100 ^ 1001 = 00101 01100 & 1001 =01000 010000 ^ 00101 = 10101 = 21(结果) 010000 & 00101 = 0(结束) 实现 : 1 public class Num48_Add { 2 public int Add(int num1,int num2) { 3 int and = num1 & num2; 4 int xor = num1 ^ num2; 5 6 while(and!=0){ 7 int temp =

转 位运算实现加减乘除运算

不问归期 提交于 2020-03-04 19:08:58
我们知道,计算机最基本的操作单元是字节(byte),一个字节由8个位(bit)组成,一个位只能存储一个0或1,其实也就是高低电平。无论多么复杂的逻辑、庞大的数据、酷炫的界面,最终体现在计算机最底层都只是对0101的存储和运算。因此,了解位运算有助于提升我们对计算机底层操作原理的理解。 今天就来看看怎么不使用显式“ + - * /”运算符来实现加减乘除运算。 下面我们一个一个来看。 1. 加法运算 先来个我们最熟悉的十进制的加法运算: 13 + 9 = 22 我们像这样来拆分这个运算过程: 不考虑进位,分别对各位数进行相加,结果为sum: 个位数3加上9为2;十位数1加上0为1; 最终结果为12; 只考虑进位,结果为carry: 3 + 9 有进位,进位的值为10; 如果步骤2所得进位结果carry不为0,对步骤1所得sum,步骤2所得carry重复步骤1、 2、3;如果carry为0则结束,最终结果为步骤1所得sum: 这里即是对sum = 12 和carry = 10重复以上三个步骤,(a) 不考虑进位,分别对各位数进行相加:sum = 22; (b) 只考虑进位: 上一步没有进位,所以carry = 0; (c) 步骤2carry = 0,结束,结果为sum = 22. 我们发现这三板斧行得通! 那我们现在还使用上面的三板斧把十进制运算放在二进制中看看是不是也行的通。

java的位运算

风流意气都作罢 提交于 2020-03-04 19:03:16
 在日常的Java开发中,位运算使用的不多,使用的更多的是算数运算(+、-、*、/、%)、关系运算(<、>、<=、>=、==、!=)和逻辑运算(&&、||、!),所以相对来说对位运算不是那么熟悉,本文将以Java的位运算来详细介绍下位运算及其应用。 1、 位运算起源   位运算起源于C语言的低级操作,Java的设计初衷是嵌入到电视机顶盒内,所以这种低级操作方式被保留下来。所谓的低级操作,是因为位运算的操作对象是二进制位,但是这种低级操作对计算机而言是非常简单直接,友好高效的。在简单的低成本处理器上,通常位运算比除法快得多,比乘法快几倍,有时比加法快得多。虽然由于较长的指令流水线和其他架构设计选择,现代处理器通常执行加法和乘法的速度与位运算一样快,但由于资源使用减少,位运算通常会使用较少的功率,所以在一些Java底层算法中,巧妙的使用位运算可以大量减少运行开销。 2、 位运算详解   Java位运算细化划分可以分为按位运算和移位运算,见下表。 细化 符号 描述 运算规则 按位运算 & 与 两位都为1,那么结果为1 | 或 有一位为1,那么结果为1 ~ 非 ~0 = 1,~1 = 0 ^ 异或 两位不相同,结果为1 移位运算 << 左移 各二进制位全部左移N位,高位丢弃,低位补0 >> 右移 各二进制位全部右移N位,若值为正,则在高位插入 0,若值为负,则在高位插入 1 >>>

php位运算二进制运算法则

一世执手 提交于 2020-03-04 00:08:47
位运算(二进制运算法则) 位运算 二进制: 所谓的二进制就是逢二进一(0、1)简单,易于电子方式实现 基本概念: 1.二进制的最高位是符号位:0是正数,1是负数。 2.正数的原码,反码,补码都是一样。 3.负数的反码=它的原码符号位不变,其他位取反(0->1,1->0)。 4.负数的补码=它的反码+1 0的反码,补码都是0. 6.Php没有无符号数,换言之,php中数都是有符号的 7.在计算机运算的时候,都是以补码的方式来运算的 二进制三个重要概念 1.原码 2.用二进制表示一个数字,这个码就是原码 1----> 00000000 00000000 00000000 00000101=1 2的零次方+0 2的一次方+1*2的二次方=1+0+4=5 运算规则: 按位与&:两位全为1, 结果为1 按位或|:两位一个为1, 结果为1 按位异或^:两位一个为0,一个为一, 结果是1. 按位取反~ :0->1,1->0。 来源: CSDN 作者: 小祈祈 链接: https://blog.csdn.net/qq839534800/article/details/104641361