用函数unsigned int reverse_bit(unsigned int value)实现想要的功能
value是我们想要求的值。
#include
#include
unsigned int reverse_bit(unsigned int value)
{
int sum= 0;
int n = 31;
for(;value != 0,n != 0; value = value >> 1,n--)
{
if(value & 1)
{
sum += 1*pow(2,n);
}
}
return sum;
}
int main ()
{
printf("%u\n",reverse_bit(25));
return 0;
}
本题用到数学库的函数pow,其作用是计算幂,比如pow(2,n)是计算2的n次幂。
大致思路是:一个数–>00000000 00000000 00000000 00011001
当最后一位是1时,我们都将它乘以2的31次方,接着将31减1(幂数减减),并累计每次乘积和;若最后一位是0则只进行幂数减减。
但是如果最后一位是1,那么每次都需要进行累加和计算,所以,这样的程序,效率往往还是很差的。上面的程序感觉没有错误,但是当你输入1时,看看运行结果是不是你想要得到的。所以上面的程序是错误的。
针对上面程序,下面提供了另一种解决方案:
#include
#include
unsigned int reverse_bit(unsigned int value)
{
int ret = 0;
int one = 0;
int i = 0;
for(i=0; i<32; i++)
{
one = value & 1;
ret = ret | one;
ret <<= 1;
value = value >> 1;
}
return ret;
}
int main ()
{
printf("%u\n",reverse_bit(25));
return 0;
}
这个程序主要采用了移位运算符,我们来验证一下结果:
当我们看到运行结果中的25对应二进制翻转后的十进制数并不符合我们的要求时,肯定知道程序写错了,但是你知道错在哪里吗?我们不妨把实参改为1,即把主函数改为:
int main ()
{
printf("%u\n",reverse_bit(1));
return 0;
}
让我们看看结果:
此时你发现如果把1移到最高位,输出的应该是2147483648,但是为什么却是0呢?
那我们再把主函数改成:
int main ()
{
printf("%u\n",reverse_bit(2147483648));
return 0;
}
我们再来看看结果:
此时运行结果为什么不是1而是2呢?我们发现在32位系统下,本来我们只需要移动31次就能达到把最低位移到最高位上,而程序的for循环中也正是移动31次。当进入执行for循环时,ret是在执行完一次操作后才开始左移,所以无形当中已经增加了一次左移操作。那好,既然运行结果不正确,是因为ret多移动了一位,那么我们就试着把for循环中的32改成31,也就是:
for(i=0; i<31; i++)
{ one = value & 1; ret = ret | one; ret <<= 1; value = value >> 1; }
主函数中的输出我们依然用:
printf("%u\n",reverse_bit(1));
紧接着我们验证一下结果:
结果对了!那么程序就对了!
那么我们试着把主函数改为:
int main ()
{
printf("%u\n",reverse_bit(2147483648));
return 0;
}
我们再来验证一下结果
为什么结果依然不是1呢?我们换个角度思考,既然ret是在第一次操作后多移动了一次,那么我们可不可以在ret执行第一次操作之前先移动一位,而ret初始化为0,所以既然一共要移动31位,又不影响运行结果,那么我们可以改变一下for循环中语句的执行顺序
我们看看正确的程序:
#include
#include
unsigned int reverse_bit(unsigned int value)
{
int ret = 0;
int one = 0;
int i = 0;
for(i=0; i<32; i++)
{
ret <<= 1;
one = value & 1;
ret = ret | one;
value = value >> 1;
}
return ret;
}
int main ()
{
printf("%u\n",reverse_bit(1));
return 0;
}
此时再去验证运行结果是否正确的工作就留给你们啦~~~~