Codeup[100000579]进制转换[解法一]

博客详细解析了如何处理超过long long数据类型的10进制数转其他进制的问题。通过输入字符串,将其转换为整数序列,模拟除法操作来完成转换。文章以145除以2为例,解释了除法过程,并提供了相应的C语言代码实现。虽然运行时间较长,但理解这一过程能有效解决大整数转换难题。作者还提到存在更简便的解法,会在后续分享。

题目要求如下:
在这里插入图片描述可以看到会输入1个长度不超过30位的10进制数,与之前问题Codeup 又一版A+B[100000579]不同。因此使用一般情况下long long数据类型已经是不行的,因为long long数据类型,最大容纳的整数大小为 2 64 − 1 2^{64}-1 2641,而此时输入的数值可能是 1 0 30 10^{30} 1030,很明显大于前者。
此时,我们可以输入1个字符串,然后将其转换为整数序列,再进行除法的模拟操作,从而解决这个问题。
这里我们定义1个结构体,其有3个成员:

typedef struct BigNumber
{
	int d[1000]; // 数的序列
	int len;     // 长度
	int r;       //余数
} bign;

其中变量d是1个int数组,其里面存储对应值的序列,而len用于表示数值的长度,主要是为了方便操作,而r存储对应的余数。
我们将读取进来的字符串转换成对应的数值序列:

bign change(char *str){
	bign a = {0};
	a.len = strlen(str);
	for (int i = 0;i < a.len; ++i)
	{
		a.d[i] = str[a.len-i-1] - '0';
	}
	return a;
}

其中字符串的低位对应数值序列的高位,而字符串的高位对应数值序列的低位。
对于字符的减法,比如'9'-'0',计算机会将其转换为整数,即57-48=9,这样避免了强制转换数据类型的过程。
接着是除法的过程,假设我们对145除以2,那么其计算过程为:

 2  | 1 4 5         1
    ----------
 2  | 0 7 2  |      0
    -----------
2  |    3 6  |      0
   ------------               
         1 8  |       0
   -----------
           9  |       1
     ----------- 
          4   |        0
     -----------
         2   |        0
     -----------
         1  |         1     

我们可以得到如下的步骤:

  1. 由于1小于2,因此商为0,往后借1位,得到14
  2. 14大于2,可以除,商为7,接着是5除以2,得到商为2,余1
  3. 接着是商72对2进行除法,余0
  4. 依次类推,直到商为0

按照这种思路,我们有如下的代码:

int r = 0;  // 余数
for (int i = a.len-1; i >= 0; --i) //从序列高位开始
	{
		r = r * 10 + a.d[i]; //对应高位的值
		if(r<b){             //余数小于除数,商为0
			c.d[i] = 0;  
		}else{
			c.d[i] = r / b;  //对应高位上的商
			r = r % b;       //获得新的余数
	}
}

将上面的过程组合起来,于是有如下完整的代码:

#include <stdio.h>
#include <string.h>

typedef struct BigNumber
{
	int d[1000];
	int len;
	int r;
} bign;

bign change(char *str){
	bign a = {0};
	a.len = strlen(str);
	for (int i = 0;i < a.len; ++i)
	{
		a.d[i] = str[a.len-i-1] - '0';
	}
	return a;
}

bign divide(bign a, int b){
	bign c = {0};
	c.len = a.len;
	int r = 0;
	for (int i = a.len-1; i >= 0; --i)
	{
		r = r * 10 + a.d[i]; //进位,比如原位是1,此时由1变成10
		if(r<b){
			c.d[i] = 0;
		}else{
			c.d[i] = r / b;  //商
			r = r % b;       //获得新的余数
		}
	}
	c.r = r;
	// 去掉高位上的0
	while(c.len-1>=1 && c.d[c.len-1]==0){
		c.len--;
	}
	return c;
}

int main(int argc, char const *argv[])
{
	char b[31];
	while(~scanf("%s",&b)){
		bign c = change(b);
		int arr[128] = {0};
		int count = 0;
		//至少执行1次
		do{
			c = divide(c, 2);
			arr[count] = c.r;
			count++;
		}while(c.d[c.len-1]!=0);
		for (int i = count-1; i >=0; --i)
		{
			printf("%d", arr[i]);
		}
		printf("\n");
	}
	return 0;
}

这里我们使用do…while循环体让循环至少执行1次,避免输入0导致跳过循环情况的出现。
最后是最终通过后的结果:
在这里插入图片描述
整个过程运行时间比较长,但是原理是一样的,明白了整个过程就可以解决这个看起来棘手的问题了。
当然这只是其中1种解法,通过模拟除法的方式来解决,后续有时间再发表其他更为方便的解决方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值