神奇的位运算——进制转换问题(16转8)

说道位运算符,应该都了解,但是很少有人会用,在网上看别人的代码,我至今只见过一道题用到了位运算符,并被它深深的搞晕了(当然,他搞晕我是要负责的,我现在已经深深的迷上了他,真的是太神奇了),位运算符的原理容易懂,也都知道他运算的效率很高,但是他究竟怎么去用,用在什么地方,我想不少人都说不清楚,所以当我看到位运算符可以这么玩的时候,我感到很神奇!
首先,我们先来一个简单的程序来说明位运算符的神奇。
问题是:如何交换两个变量的值?
看到这个问题,我想九成的人会说定义第三方变量,通过第三方变量去交换值。
对,这是个很直观很容易想到的方式。但是我还知道两种不用第三方变量的方法,并且其中有一种方法最安全,最高效——利用位运算符(^)交换,简单,易记。(首先需要给大家一个公式,这个公式是实现这个方法的核心:a ^ b ^ b = a)
void exchange(int a, int b)
{
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    return ;
}
看到这里,是不是十分不可思议?其实这很好理解,只要你知道(^)这个符号是怎么运算的,用笔写写画画就出来了……这里就不解释了,有兴趣的人去试试就成了。

通过这个小算法,我想大家的兴趣就已经被吸引住了,那么我们就来尝尝我们的硬菜吧!
题:给定n个十六进制正整数,输出对应的八进制数。
题好理解,通常这样的问题,我们都先将其转换为2进制,再转成8进制的好,废话少说,代码如下。
#include <stdio.h>
#include <string.h>

char str[100005], num;
void Fun(int i, int state)
{
    int temp;
    if(i < 0)
    {
        if(num != 0)  //此时的num转二进制后的有效位数小于三位,即num小于8
        {
            printf("%d", num);
        }
        return;
    }
    if(state != 3)
    {
        temp = str[i] >= '0' && str[i] <= '9' ? str[i] - '0' : str[i] - 'A' + 10;
        temp <<= state;  //state指每次将16进制转2进制后,截取最后三位后剩余几位
        num |= temp;     //把二进制的num和二进制的temp相加(等同于十进制之间的加,因为对应num位数的temp的后几位在上一步左移时填补了0)
        temp = num;
        num >>= 3;
        Fun(i - 1, state + 1);
        printf("%d", (temp & 1) + (temp & 2) + (temp & 4));  //相当于将temp转二进制后的最后三位取出并转8进制
    }
    else
    {
        temp = num;
        num >>= 3;
        Fun(i, 0);
        printf("%d", (temp & 1) + (temp & 2) + (temp & 4));
    }
}

int main()
{
    int n;
    scanf("%d", &n);
    while(n--)
    {
        num = 0;
        scanf("%s", str);
        Fun((int)strlen(str) - 1, 0);
        printf("\n");
    }
    return 0;
}
看到代码,我变成了一个大写的懵比,然后我决定跟它死磕到底,我拿出自己的法宝,笔和纸,自己一步一步模拟运行并尝试去理解每一步代码的意图(有的时候,编辑器的断点分步功能还没有我们的纸和笔用这方便快捷,我们可以前后对比着去发现代码中的一些奥妙)。
算法,我认为是不能细细的讲的,只能提供一个大致的思路,具体的过程需要自己去悟,因为只听那是容易变成懵比的,所以,我只能推荐你们去带入一个值去尝试着一步一步的往后推!这样有利于我们对代码的理解,大致的思路和方向我已经在代码中注释了,希望可以帮助大家去好好理解!
全部评论

相关推荐

10-07 23:57
已编辑
电子科技大学 Java
八街九陌:博士?客户端?开发?啊?
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务