突然发现的位运算神奇事件,与大家共同分享- -...

qq120848369 2010-05-25 10:38:23
#include <stdio.h>
#include <stdlib.h>

int main()
{
int a,b,c,d,e,f;
a=257/8;
b=257>>3;
c=457%32;
d=457-((457>>5)<<5);
e=457-((457>>4)<<4);
f=457-((457>>3)<<3);
printf("sizeof(int):%u, a:%d,b:%d,c:%d,d:%d,e:%d,f:%d",sizeof(int),a,b,c,d,e,f);
return 0;
}

Ok,今天偶遇这么一个问题,感觉很新鲜.

大家都知道右移1位相当于对数值除2并取整。 c=457%32, 我试图用移位代替除法,所以有了d=457-((457>>5)<<5); 结果当然一样。
再看e=457-((457>>4)<<4); 结果依旧一样, 再看f=457-((457>>3)<<3); 结果就不对了.
分析457的二进制, 111001000 . 发现按照我们的想法,除32应该是右移5位,即除了5次2,d就是这个想法,结果也正确了.
但为什么少除1次也对呢? 看二进制发现4次移位并没有比移动5位带来更多的变化,通过4左移后与右移5位再左移5位结果一样.
而f则不对,因为不像d,e那样,f没有把那个1丢失,所以结果不是正确的了.

大家对此有什么感想么,我感觉很郁闷. 怎么这么巧.
...全文
249 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
tananade 2010-05-26
  • 打赏
  • 举报
回复
mark~~~~
东莞某某某 2010-05-26
  • 打赏
  • 举报
回复
弄清本质
没啥的
阿磊2013 2010-05-26
  • 打赏
  • 举报
回复
没看明白什么意思
建鼎呓语 2010-05-26
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 lstyk 的回复:]

没看懂什么意思…………
PS:
457的二进制:111001001
[/Quote]

同上,你数值就搞错了,至于运算结果自己仔细分析一下就好了,没什么大惊小怪的。
harderman 2010-05-26
  • 打赏
  • 举报
回复
UP 5楼!
nima01 2010-05-26
  • 打赏
  • 举报
回复
LZ去试试11111111的右移,移不同的位结果都是不同的,LZ那个只是刚好移4位和5位再回来的时候结果刚好一样而已
qq120848369 2010-05-26
  • 打赏
  • 举报
回复
原来除16与除32,64取余本来就相同,我还以为二进制运算和算术运算冲突了呢.
gelu1040 2010-05-26
  • 打赏
  • 举报
回复
你难道不知道所有位权构成一个2为底的等比数列吗?
2^0 2^1 2^2 2^3 ... ... 2^n
所以用移位的方法能够乘除2的倍数,答案正确。

另外,向不同方向移动两次,必然带来位的损失。
INT32 t;
t>>=32;
t必然等于零。
t<<=31;
t>>=31;
只剩下0位,等价于 t&=00000001;高31位没掉了。


guzhijie1981 2010-05-26
  • 打赏
  • 举报
回复
C规定左移是逻辑左移;而右移可以逻辑的也可以算术的;所以你的代码在不同的机器上有不同的结果;
原因在于你的最高位是否为1;如果是0;逻辑和算术右移是等价的;但是如果是1;就不等价来;
建议看看C99标准
mskmc_mc 2010-05-26
  • 打赏
  • 举报
回复
天才,可以把牛 和 爱 拿下了
  • 打赏
  • 举报
回复
你先右移4位再左移4位,相当于进行%16的操作,同理,先右移3位再左移3位,相当于进行%8的操作,这里d和e相同是因为457的第5位碰巧为0,f是进行%8的操作的结果,你想想会等于9么?
赵4老师 2010-05-26
  • 打赏
  • 举报
回复
VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
品茶 2010-05-26
  • 打赏
  • 举报
回复
打酱油
ArtiFly2000 2010-05-26
  • 打赏
  • 举报
回复
LZ程序的输出是什么
没看出来有什么神奇的东西
我运行这个程序打印出来的值都很正常
457%8 = 457 - (457>>3)<<3 = 1
LZ打印出来的不是这个结果吗?
qq120848369 2010-05-25
  • 打赏
  • 举报
回复
括号打错了吧,a=a&32-1; 这样才对。
qq120848369 2010-05-25
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 yq_118 的回复:]

a%32 == a&(32-1)
[/Quote]

技巧帝. 能证明一下么,不喜欢死记硬背.
stein42 2010-05-25
  • 打赏
  • 举报
回复
a%32 == a&(32-1)
qq120848369 2010-05-25
  • 打赏
  • 举报
回复
457二进制的确不是我写那个,不影响分析.
7怎么说也是个奇数...我把最低位的1丢了,用计算器算得,抄过来可能抄错了..
qq120848369 2010-05-25
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 selooloo 的回复:]

LZ搞错了吧
457的二进制是 111001001
右移的话最左边的1会丢失,所以再左移回来值就变了

e=457-((457>>4)<<4);
右移4位数 变成11100,再左移4位 变成11100 0000,后来的1001就丢失了,所以计算出来的结果是9,也就是1001的值

因为111001001 第五位是0所以右移5位在左移结果和右移4位相同
同理,右移6位结果也一……
[/Quote]

我表达可能不太清楚,和你的意思是一样的.
selooloo 2010-05-25
  • 打赏
  • 举报
回复
LZ搞错了吧
457的二进制是 111001001
右移的话最左边的1会丢失,所以再左移回来值就变了

e=457-((457>>4)<<4);
右移4位数 变成11100,再左移4位 变成11100 0000,后来的1001就丢失了,所以计算出来的结果是9,也就是1001的值

因为111001001 第五位是0所以右移5位在左移结果和右移4位相同
同理,右移6位结果也一样
加载更多回复(4)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧