位运算

原码, 反码, 补码

廉价感情. 提交于 2020-11-04 06:09:17
原码, 反码, 补码 很好的文章,博主证明很详细 1.如果你还在为 计算机中的+0,-0困惑 2.如果你还不理解补码如何演变的 原码, 反码, 补码 详解 原文,有些未更正的错误,比如这个举例有问题: 运用同余数的两个定理: 反身性: a ≡ a (mod m) 这个定理是很显而易见的. 线性运算定理: 如果a ≡ b (mod m),c ≡ d (mod m) 那么: (1)a ± c ≡ b ± d (mod m) (2)a * c ≡ b * d (mod m) 如果想看这个定理的证明, 请看: http://baike.baidu.com/view/79282.htm 所以: 7 ≡ 7 (mod 12) (-2) ≡ 10 (mod 12) 7 -2 ≡ 7 + 10 (mod 12) 现在我们为一个负数, 找到了它的正数同余数. 但是并不是7-2 = 7+10, 而是 7 -2 ≡ 7 + 10 (mod 12) , 即计算结果的余数相等. 应该是: (-5) ≡ 7 (mod 12) (-2) ≡ 10 (mod 12) --> -5 -2 ≡ 7 + 10 (mod 12) -7 ≡ 5 (mod 12) 注:如有问题欢迎大家指正。 来源: oschina 链接: https://my.oschina.net/u/96193/blog/297503

位运算卷积-FWT

穿精又带淫゛_ 提交于 2020-04-08 04:49:41
问题 给出两个幂级数 \(f,g\) ,求 \[h=\sum _i\sum _jx^{i\oplus j}f_ig_j \] 其中 \(\oplus\) 是可拆分的位运算。 算法 由于位运算具有独立性,可以一位位地考虑。 设 \(f=(f_0,f_1)\) ,即最高位为 0 的部分和最高位为 1 的部分。我们希望把这个卷积转化为点积来做。即 \[T\begin{bmatrix}f_0 \\f_1 \end{bmatrix}\cdot T\begin{bmatrix}g_0 \\g_1 \end{bmatrix}=T\begin{bmatrix}h_0 \\h_1 \end{bmatrix} \] 按照 \(f,g,h\) 的对应关系,对比系数容易得到 \(T\) 。 那么我们就可以先对 \(f,g\) 递归进行上述变换,然后再点积起来,逆变换回去,这样就能得到我们需要的 \(h\) 。显然逆变换可以直接用矩阵 \(T^{-1}\) 做同样的操作。 复杂度为 \(O(nk^2\log n)\) , \(k\) 为位状态数。 拓展 上面的过程只用到了位运算的可拆分性,所以可以尝试拓展一下。例如更高进制的位运算卷积,可以用完全一样的方法来做。做之前只要定义好位的运算即可。例如 [清华集训2016]石家庄的工人阶级队伍比较坚强 中的三进制卷积,类比二进制异或,定义三进制不进位加法

C语言之位运算

二次信任 提交于 2020-04-03 22:17:03
位运算 1).定义. 指的是1个二进制数据的每一位来参与运算. 位运算的前提: 是这个数必须是1个二进制. 注意: a). 参与位运算的二进制数据必须是补码形式. b). 位运算的结果也是二进制的补码形式. 2).按位与: & 参与按位与的两个二进制数.如果都为1 那么结果就为1 只要有1位为0 那么结果就为0. 3 & 2; 第1步骤:先得到两个数的二进制补码形式. 3的补码: 00000000 00000000 00000000 00000011 2的补码: 00000000 00000000 00000000 00000010 ------------------------------------------------------- 00000000 00000000 00000000 00000010 2 -3 & 4; -3的原码:10000000 00000000 00000000 00000011 -3的反码:11111111 11111111 11111111 11111100 -3的补码:11111111 11111111 11111111 11111101 4的补码: 00000000 00000000 00000000 00000100 ------------------------------------------------------

[LeetCode] 231. Power of Two

泄露秘密 提交于 2020-03-25 13:47:54
题意很简单,问一个数字n是否是2的几次幂。思路是用位运算做,如果你对位运算很敏感,你会发现,所有2的某次方的数字,转化成二进制之后,都只有一个1。比如 2->0010, 4->0100, 8->1000...... 所以思路是比较n & n-1是否等于0即可。因为如果n是2的某次方,比它小1的数字里面一定是一堆1。 举个例子,16的二进制是10000,15的二进制是01111,两者做AND运算得到0。代码如下, 1 var isPowerOfTwo = function (n) { return n > 0 && (n & (n - 1)) === 0 ; }; 来源: https://www.cnblogs.com/aaronliu1991/p/11675164.html

枚举enum

半城伤御伤魂 提交于 2020-03-24 16:22:00
枚举值:它是一个整形(int) 并且,它不参加内存的占用和释放 枚举定义变量即可直接使用,不用初始化. 枚举的定义如下: 方式一: typedef enum{ //在这个地方,可以定义相同的名称,给要用到的类型起个标识符,这个地方,是可以省略的 unknown, //大括号里面的内容,依据程序员的需要来填充,使用逗号隔开,最后一个可以不使用符号,默认的序号是从0开始的,最好在标记时给它赋值=0 //如果在中途给它定义了数字,比如unknown=7,则以后的字符的序号依次递增,iPad=8 iPad, iPhone }TYPES;//枚举的名称,并且使用分号来结束 方式二: enum 名称{ 枚举数据表 }; enum type{ }; 补充:2015年07月25日 //---------------------------------------------------------------------------------- 1、枚举的定义写在哪里? 答:跟在 #import “”后面写,写在类的前面,确保枚举的作用范围 方式三: 1)亦可以如下定义(推荐:结构比较清晰): 格式:typedef NS_ENUM(NSInteger, 名称){}; typedef NS_ENUM(NSInteger, Test1) { //以下是枚举成员 Test1A = 0, Test1B

位运算经典例题

别等时光非礼了梦想. 提交于 2020-03-24 08:02:34
异或实现加法 int add(int a, int b){ return a & b == 0 ? a ^ b : add(a ^ b, (a & b) << 1); } Single Number 问题描述:数组中有一个元素出现了p次,其他元素均出现了k次,求该元素 解决方法: 正常思路是统计每个元素出现的次数,即可求出该元素,通过位运算,我们可以实现对元素的统计 先令p = p % k,这样我们统计的上限最多为k,需要 \(m = \log \left \lceil k \right \rceil\) 个位来表示,也就是对每个位进行计数。 我们先单单看一位,比如32位整数的第一位1st,对于新来的数,如果新来的数该位为1,则我们需要增加第一位对应的m-counter计数器,当计数器达到k时清空为0,最后的p的二进制表示对应的x即可。 先用一个例子说明一下,如k=5,p=3那么对于32位整数的第一位而言,如果single number的该位为1的话,那么该位对应的计数器必定计数了k * r(r为整数) + p次,由于p=3(二进制11)那么该计数器的第一位和第二位都会被置为1,其他位同理,返回x1或者x2即可 现在的主要问题就为当一个位上的1或0来的时候 如何在计数器上实现加法 如何在计数器计数达到k时清零 对于第一个问题,我们知道只有当前m-1个数全是1的时候,遇到0才会进位,

两个与位运算有关的小问题

跟風遠走 提交于 2020-03-24 08:01:15
两个与位运算有关的小问题 在读《编程之美》一书时,书中提到两个小问题: 1.如何求算N!的二进制表示最低位1的位置。 2.如何用最简便最快的方法判断一个正整数是否是2的方幂。 对于第一个问题:对于任何一个整数n,当表示成二进制时,若最低位为1,则该数肯定是奇数,否则为偶数。若是奇数,则n肯定不含质因子2.例如9的二进制形式是1001,最后一位位1,则肯定不含因子2,而12的二进制形式是1100,则肯定含因子2.但是将1100右移2位就变成0011,即将12除以2^2,此时0011为奇数。从这里可以发现一个规律,要求一个数的二进制表示形式最低位1的位置,相当于求算n有多少个因子2。因为假如一个整数表示成二进制是r0r1r2.....rk.....rn,如果rk是最低位为1的位置,那么从r(k+1)到rn都为0,此时将其右移(n-k)位,则rk在最低位,此时该二进制必定不包含因子2,而将二进制右移1位相当于除以2,即求算rk的位置相当于求算因子2的个数。而求算N!中含有2的个数很容易求算。 int location(int n){ int low=0; while(n) { low+=n>>1; n>>=1; } return low;} 对于第二个问题:如果一个整数是2的方幂,即能表示成2^n的形式,则表示成二进制必然是rn.....rk....r1r0,rn为1,其他所有的位都为0

使用位运算实现int32位 整数的加减乘除

穿精又带淫゛_ 提交于 2020-03-22 22:20:59
3 月,跳不动了?>>> 使用位运算实现int32位 整数的加减乘除 我觉得比较难想的是加法吧。 首先加法,脑海中脑补二进制加法,相同位相加,超过2 ,则进1,留0 那么用位运算怎么实现呢?其实理解了异或和与操作,就很容易想出来了。 我觉得异或操作和与操作完全就是实现加法的。 异或就是相同位相加最后留下的结果,而与就是相同位相加是否进1的结果。 异或:相同位 相同为0,不同为1。 与:相同位 都是1结果才是1,否则都是0。 这不就是二进制相加吗? 异或 与 1+1 = 0 进1 1+0 = 1 进0 0+0= 0 进0 所以加法就是,每次先异或一下,然后算出来进位的结果,再左移一位,因为是进位嘛 static int Add ( int x, int y ) { while (y != 0 ) { int z = x; x ^= y; y &= z; y <<= 1 ; } return x; } 减法,就很容易实现了,减一个数等于加上这个数的负数 一个数怎么变成负数呢?取反码然后+1 所以减法就是 static int Sub ( int x, int y) { int z = Add(~y, 1 ); return Add(x, z); } 那么乘法呢,简单的想法是,一个一个想加呗,a* b不就是b个a相加,对不对,想法的是对的,但是我们要利用二进制的思想,也就倍增的思想。

C 位运算

与世无争的帅哥 提交于 2020-03-21 10:28:49
位运算符 位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示: p q p & q p | q p ^ q 0 0 0 0 0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 1 假设如果 A = 60,且 B = 13,现在以二进制格式表示,它们如下所示: A = 0011 1100 B = 0000 1101 ----------------- A&B = 0000 1100 A|B = 0011 1101 A^B = 0011 0001 ~A = 1100 0011 << 二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。 A << 2 将得到 240,即为 1111 0000 >> 二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。 A >> 2 将得到 15,即为 0000 1111 来源: https://www.cnblogs.com/nanqiang/p/9988669.html

Java位运算符及二进制常识

﹥>﹥吖頭↗ 提交于 2020-03-18 17:40:14
3 月,跳不动了?>>> 一、位运算    二、位移运算    三、二进制数   以Java中最常使用的int类型为例(32位)。    ㈠ 符号位   二进制数最左端的数字为符号位: 0代表正,1代表负 。 ㈡ 最大与最小   ⑴ 1是最小的正整数,符号位为0,最后一位为1,其它全部为0。   递增:二进制数右端每次加1(逢2进1),一直到31个非符号位的0全部变为1,得到最大的正整数2147483647。   ⑵ -1是最大的负整数,符号位为1,其它31位也全部为1。   递减:二进制数右端每次减1(逢0借1),一直到31个非符号位的1全部变成0,得到最小的负整数为-2147483648。 ㈢ 原码、补码、反码   ⑴ 原码   根据数学上的表示习惯:“+”代表为正数,只要将“+”变为“-”,那么就是对应的负数。譬如 +1 对应的负数为 -1。   根据这个原则,二进制数的负数表示本来应该如下图:      以正数的二进制数表示为基准,负数的表示只改变符号位,这样的表示方式就是 原码 。因此, 正数的表示方式都是原码。   事实上的二进制的负数并不是如上面的原码这样表示,譬如-1是32个1。那么这样的表示方式是如何得到的呢?   ⑵ 反码   反码就是将原码除符号位以外的值全部取反,原来是1的变为0,原来是0的变为1。例如使用-1的原码得到的反码如下图所示:      ⑶ 补码