移位运算总结 第1篇
A= B=
符号位单独处理;
被乘数逐步左移,其数值是本身还是0由乘数的某一位决定的;
四个部分积分别相加;
乘积位数扩大一倍
A·B=A·
=
=(A+)
=[0·A+(A+)]
={A+[0·A+(A+)]}
=2^(-1) {1·A+ 2^(-1) [0·A+2^(-1) (1·A+2^(-1)(1·A+0))]}(在xxx制中2^(-1)=)
乘法运算可用加和移位实现n=4,加4次,移4次由乘数的末尾决定被乘数是否与原部分积相加,然后->1位形成新的部分积1,同时乘数->1位(末尾丢掉),空出高位存放部分积的低位。被乘数只与部分积的高位相加
(1)原码1位乘运算规则以小数为例
2)例题:
已知x= y= 求[x·y]原
则[x·y]原=
移位运算总结 第2篇
9、不用temp交换两个整数
10、计算绝对值
else x= a; 等价于 x= a ^ b ^ x; 16、x 的相反数表示为 (~x+1)
比较浅显的来说,xxx位就是乘以2的n次方,右移n位就是除以2的n次方。具体细节如下:
C语言里的左移和右移运算 2006-09-30 13:52
先说左移,左移就是xxx一个数的所有位都向左移动若干位,在C中用<<运算xxx如:
int i = 1; i = i << 2; //xxxi里的值左移2位
也就是说,1的2进制是000…0001(这里1前面0的个数和int的位数有关,32位机器,gcc里有31个0),左移2位之后变成 000…0100,也就是10进制的4,所以说左移1位相当于乘以2,那么xxx位就是乘以2的n次方了(有符号数不完全适用,因为左移有可能导致符号变化,下面解释原因)
需要注意的一个问题是int类型最左端的符号位和移位移出去的情况.我们知道,int是有符号的整形数,最左端的1位是符号位,即0正1负,那么移位的时候就会出现溢出,例如:
int i = 0x40000000; //16进制的40000000,为2进制的01000000…0000 // 40000000 共八位,故用xxx制表示为32位。 i = i << 1;
那么,i在左移1位之后就会变成0x80000000,也就是2进制的100000…0000,符号位被置1,其他位全是0,变成了int类型所能表示的最小值,32位的int这个值是-2147483648,溢出.如果再接着xxxi左移1位会出现什么情况呢? (这个真不知道?????????) 在C语言中采用了丢弃最高位的处理方法,丢弃了1之后,i的值变成了0.
左移里一个比较特殊的情况是当左移的位数(>>32)超过该数值类型的最大位数时,编译器会用左移的位数去模类型的最大位数,然后按余数进行移位,如:
int i = 1, j = 0x80000000; //xxxt为32位 i = i << 33; // 33 % 32 = 1 左移1位,i变成2 j = j << 33; // 33 % 32 = 1 左移1位,j变成0,最高位被丢弃
在用gcc编译这段程序的时候编译器会给出一个warning,说左移位数>=类型长度.那么实际上i,j移动的就是1位,也就是33%32后的余数.在gcc下是这个规则,别的编译器是不是都一样现在还不清楚.
总之左移就是: 丢弃最高位,0补最低位(不懂????)
再说右移,明白了左移的道理,那么右移就比较好理解了.
右移的概念和左移相反,就是往右边挪动若干位,运算符是>>.
右移对符号位的处理和左移不同,对于有符号整数来说,比如int类型,右移会保持符号位不变,例如:
int i = 0x80000000; i = i >> 1; //i的值不会变成0x40000000,而会变成0xc0000000
就是说,符号位向右移动后,正数的话补0,负数补1,也就是汇编语言中的算术右移.同样当移动的位数超过类型的长度时,会取余数,然后移动余数个位.
总之,在C中,左移是逻辑/算术左移(两者完全相同),右移是算术右移,会保持符号位不变.实际应用中可以根据情况用左/右移做快速的乘/除运算,这样会比循环效率高很多.
unsigned char a; a=1; //0b00000001 a<<=1; //0b00000010 a左移1位等效于a=a*2 a<<=2; //0b00001000 a左移2位等效于a=a*2的2次方(4) a<<=3; //0b01000000 a左移1位等效于a=a*2的3次方(8) a<<=1; //0b10000010 a左移1位等效于a=a*2 a<<=1; //0b00000000 a再次左移1位后溢出了,结果变成0了
移位运算总结 第3篇
接下来我们再来看基于反码的算数移位。
<1> 先来看正数
。由于正数的反码表示和原码表示是一模一样的,所以对于正数的算数移位,不管是左移还是右移,处理的方法都是和原码一样。
这是反码表示的正数,需要采取的一个策略,和原码是一样的。
<2> 再来看负数
,也就是符号位为 1 的数,这种数的反码尾数部分和原码是完全相反的, 1 变成 0、0 会变成1。反码的 1 相当于原码的0,反码的 0 相当于原码的1。
所以对负数的算数移位,进行补位的时候,需要注意,我们补的都是1,这是对于反码的算数移位。
正数和负数我们需要补充的这个位是不一样的。
移位运算总结 第4篇
余数为正:上商1
余数为负,上商0,恢复余数
和传统除法的区别:余数左移而不是原来的除数右移;由于先做的是减法操作,上商0的时候,不应该做减法,所以要恢复余数,恢复余数之后,再xxx余数左移1位,它的值扩大2倍;和除数再进行比较,以决定下一个上商为0或1,循环
(2)不恢复余数法(加减交替法)
恢复余数法运算规则
解:[x]原= [y]原= [y*]补= [-y*]补=
符号位x=1与y=1异或得到为0
x^* / y^*=
[x/y]原=
特点:
移位运算总结 第5篇
接下我们再来看。最后一种移位运算叫做循环移位
。
顾名思义,所谓循环,就是指当我们进行比如循环左移的时候,移出来的这一位会被放到我们需要填补的空位。
在移位的时候,整个xxx制串是进行循环补位的。
应该很好理解,当我们进行循环右移的时候,也是类似的,从右边移出来的这一位又会跑到应该补充的位置去。
还有一种比较特殊的循环移位,就是带进位位的这种情况。
先来解释一下什么叫进位位,也就我们标注的CF这一位。
进位的概念大家都知道了,比如我们对两个8位的xxx制数进行加法操作,当我们运算到最高位的时候, 1 加 1 等于 0 往高位进1,由于机器字长有限,寄存器里只能保存 8 个xxx制位,而最高位又确实产生了 1 这样的进位,因此为了实现超过 8 比特的这种数据的加法,计算机硬件里边会包含这样的所谓的进位的位,来记录下之前这些低位的运算有没有产生进位。
xxx进位保留下来之后,我们在进行之后的更高字节的运算的时候,就可以得到正确的结果 0 加 1再加上刚才保留的进位1,用这样的方式我们就可以不断地往高位进行计算。
所以这就是所谓的进位位的作用。
总之它里面要么存了一个1,要么存了一个0。
现在当我们考虑上进位之后,再进行循环左移,产生的效果就是这样的。
会xxx原本数值位的最高位xxx它放到进位位这个地方,而原本的进位位会来补充出现了空位这个样子。
这就是带进位位的循环左移。
带进位位的循环右移也是类似的。无非就是xxx末尾的低位放到进位的位置,而原本的进位xxx它放到最高位出现空缺的位置。
这就是所谓的循环移位。
循环移位的操作很适合用于xxx一个数据的高字节和低字节进行调换。
比如之前我们讲过一个例子,比如“啊”这个汉字,它需要占两个字节的位置,但是我们可以有大端存储和小端存储这样的两种方式。
大端存储就是先存放高字节,再存放低字节,而小端存储是先存放低字节,再存放高字节。
如果要在大端存储和小端存储之间进行转换,使用循环移位是不是很方便?我们可以循环右移8位,或者循环左移8位,就可以实现高低字节的调换。
这是循环移位的作用。
移位运算总结 第6篇
目前为止我们探讨的算数左移和算数右移是基于用原码表示的定点整数
来探讨的。
如果不是定点整数,而是定点小数
,其实也是一样的道理,一样的效果。
当我们进行算数左移
的时候,同样相当于乘以 2 的效果。算数右移
相当于除以 2 的效果。
因为所有的这些1,它们的位权在左移和右移的时候,分别会乘以 2 和除以2。(如下图)
所以定点小数我们就不再单独的探讨。