清华大学考研复试机试:10进制 VS 2进制

版权声明:本文为博主原创,未经博主允许不得转载。转载请附上原文链接。 https://blog.csdn.net/qq_38341682/article/details/88606591

题目描述

对于一个十进制数A,将A转换为二进制数,然后按位逆序排列,再转换为十进制数B,我们乘B为A的二进制逆序数。 例如对于十进制数173,它的二进制形式为10101101,逆序排列得到10110101,其十进制数为181,181即为173的二进制逆序数。

输入描述

一个1000位(即10^999)以内的十进制数。

输出描述

输入的十进制数的二进制逆序数。

分析

这道题也是一道大数运算的题目,不过这道题稍微复杂一点,因为不仅考察了大数除法,也考察了大数乘法。对于大数运算,可以使用string来存储大数,也可以使用数组来存储大数。博主之前的文章介绍了使用数组来存储大数进行运算的操作,这道题就选用string来存储进行运算。比较这两种方式后,我觉得还是使用数组比较方便一点,毕竟不用在字符和数字之间进行转换。

这道题需要注意一点的是,不能在将10进制转化为2进制后,再将2进制转化为10进制,这样会超时,这两个步骤应该同时进行。即在计算出2进制的一位数之后,就开始将其转化为10进制数,和快速幂运算有相似的思想。大数除法和大数乘法都使用博主之前文章中介绍的方法,整个转化过程结束的条件是原始输入为0,可以单独写一个函数来判断string是否为0。最后输出时一定注意要反序输出string,因为每次进位都直接加在string的最后,也就是说string的最后一个字符是最高位,所以要反序输出。

AC代码如下:

#include<iostream>
#include<string>

using namespace std;

bool is0(string str)//判断string是否为0
{
	int length = str.length();
	for(int i = 0; i < length; ++i)//需要每一位都为0
	{
		if(str[i] != '0')
		{
			return false;
		}
	}
	return true;
}

int main(void)
{
	string str;
	while(cin >> str)
	{
		int length = str.length();
		string result = "";//结果
		while(!is0(str))//string不为0
		{
			int temp = 0, tmp = 0;//temp两个过程都会使用,是连接两个过程桥梁
			for(int i = 0; i < length; ++i)//大数除法
			{
				temp = temp*10 + (str[i]-'0');//商为0时的借位
				str[i] = temp / 2 + '0';//商
				temp %= 2;//余数
			}
			int len = result.length();
			for(int i = 0; i < len; ++i)//大数乘法
			{
				//temp为上一阶段2进制数中的一位数
				//因为只是一位数,所以可以先加上,再算其他数位乘以2的值
				tmp = (result[i]-'0')*2 + temp;
				result[i] = tmp % 10 + '0';
				temp = tmp / 10;//进位
			}
			if(temp != 0)//最高位的进位
			{
				result += (temp + '0');//最高位在尾部
			}
		}
		for(int i = result.length()-1; i >= 0; --i)//反序输出,最高位在最后
		{
			cout << result[i];
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38341682/article/details/88606591