用变换的思维写程序


看到CSDN有网友提出能否用纯位运算实现if语句

int x;
//...
if(0 != x)
{
    x = 1;
}


详见

http://topic.csdn.net/u/20110710/10/19ce7d9b-01b7-4082-bb3b-1f4216c7223b.html

当然这是一道没什么意义的题目.相信楼主只是为了好玩.

乍看之下似乎没什么可能,毕竟判断是很基本的要素.

然而程序里没什么不可能,有同学就写出了以下几个方案:

 方案一:

x |= x >> 16
x |= x >> 8
x |= x >> 4
x |= x >> 2
x |= x >> 1
x &= 1


方案二:

x = x == 0? 0:1


这里方案二是不符合要求的,因为?号其实就是if判断,只是写法不同而已

方案一有点暴力.

我当时随便想了下提出了

x=((1<<x)>>(x-1))>>1

并简单测试了几个数,但后来被发现在临界点32位的时候是有问题的,不知道是否32的倍数都会有问题,没去测试,

思考其原因可能是优化的结果,或者是带进位移位造成的,因为按理论是不会有问题的.

不过做程序时一些临界点是很重要的,也是一般测试程序必要的测试点.

后来有同学提出了

x = (~((uint)x-1) | (uint)x) >> 31

比较完美的解决了问题,

x=(((uint)1<<x)>>(x-1))>>1

这个思想是让1在非0的时候不移动,在0的时候往右移1位,可惜受到进位的影响,在32倍数时出现问题.

此外还有同学提出了!!x的方案,

x=!!x


这个方案非常简洁明了,负负得正,消除其他位的1,可惜的是这个方案核心还是使用了比较

汇编代码为

cmp dword ptr [x],0  
setne al 


所以最后总结方案为

x = (~((uint)x-1) | (uint)x) >> 31


这个方案还可以有另一个形式

((-(unsigned int)x) | x )>> 31


 

不过这个确实很好玩的,有时侯写程序就应该多想想其他的思路,说不定就会有妙招出来.

遇到问题,不妨换个角度去思考,也许就豁然开朗了.

人生也是如此,在遇到绝境时,不妨换条路走走.说不定就是另一番天地.微笑


 

猜你喜欢

转载自blog.csdn.net/b2b160/article/details/6596730