进制转换小结——(以10进制为媒介、高精度转换)

目录

1、16进制和8进制的前的“0x”,“0”知识点

2、strtol函数

3、itoa函数

4、进制转化输入、输出简便用法

5、例题(1)来喽——22蓝桥杯E题

5.1、进制转换思维导图

5.2、进制转换思想

5.3、主旨展现

 6、例题(2)来喽—数制转换—(以10为媒介,y总眼中的小学数奥) 

7、例题(3)来喽——数的进制转换——(一道高精度好题)


1、16进制和8进制的前的“0x”,“0”知识点

  • 八进制数是一种逢八进一的计数体制,基数是8,用0~7表示,如077。
  • 八进制数以数字0开头。

  • 十六进制数是一种逢十六进一的计数体制,基数是16,用0~9,A~F表示,如0xFF或0XFF。
  • 十六进制数以数字0和字母x的组合0x或0X开头。其中字母x是不区分大小写的,即0x与0X等价。

  • 但是对于八进制的输出是字母o,而不是数字0。
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

int a=11;

int main()
{
    printf("%o %d %x",a,a,a);//依次将11转换成8进制,10进制,16进制打印出
    return 0;
}

2、strtol函数

  • strtol作用:将一个任意(1-36)进制数转化为10进制数,传入字符串,返回是long int型。
  • 函数为strtol(char *nptr, char *endptr, int base);

  • base是被转化的数的进制,非法字符会赋值给endptr,nptr是要转化的字符

  • 对于nptr指向的字符串,其开头和结尾处的空格被忽视,字符串中间的空格被视为非法字符。

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

int main()
{
    char buffer[20]="1000";
    char *stop;
    printf("%d",strtol(buffer, &stop, 2));//输出结果为8
//  cout<<strtol(buffer, &stop, 2);
    return 0;
}
  • 若出现非法字符,则该非法字符后面的所有字符都赋给endptr(stop)。
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

int main()
{
    char buffer[20]="1000211";//"2"为非法字符
    char *stop;
    printf("%d",strtol(buffer, &stop, 2));//仍然输出8
    return 0;
}

3、itoa函数

  • itoa作用:将一个10进制的数转化为n进制的值、其返回值为char型。
  • itoa(num, str, x);num是一个要转化的10进制数,str是转化结果,x为目标进制。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>

using namespace std;

int main()
{
    int num = 10;
    char str[100];
    printf("%s\n", itoa(num, str, 2));//输出结果为1010
    return 0;
}

4、进制转化输入、输出简便用法

hex,Hexadecimal .十六进制。
dec,Decimal ,十进制。
oct,Octal ,八进制。

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

int a, b, c;

int main()
{
    cin >> hex >> a;
    printf("%x\n", a);//16进制输入,16进制输出
    cout << dec << a << endl;//16进制输入,10进制输出

    cin >> dec >> b;
    printf("%d\n", b);//10进制输入,10进制输出
    cout << dec << b << endl;//10进制输入,10进制输出

    cin >> oct >> c;
    printf("%o\n", c);//8进制输如,8进制输出
    cout << dec << c << endl;//8进制输入,10进制输出
    return 0;
}

5、例题(1)来喽——22蓝桥杯E题

题目描述

进制规定了数字在数位上逢几进一。 X 进制是一种很神奇的进制,因为其每一数位的进制并不固定!例如说某 种 X 进制数,最低数位为二进制,第二数位为十进制,第三数位为八进制,则 X 进制数 321 转换为十进制数为 65。 现在有两个 X 进制表示的整数 A 和 B,但是其具体每一数位的进制还不确 定,只知道 A 和 B 是同一进制规则,且每一数位最高为 N 进制,最低为二进 制。请你算出 A − B 的结果最小可能是多少。 请注意,你需要保证 A 和 B 在 X 进制下都是合法的,即每一数位上的数 字要小于其进制。

输入格式

第一行一个正整数 N,含义如题面所述。 第二行一个正整数 Ma,表示 X 进制数 A 的位数。 第三行 Ma 个用空格分开的整数,表示 X 进制数 A 按从高位到低位顺序各 个数位上的数字在十进制下的表示。 第四行一个正整数 Mb,表示 X 进制数 B 的位数。 第五行 Mb 个用空格分开的整数,表示 X 进制数 B 按从高位到低位顺序各 个数位上的数字在十进制下的表示。 请注意,输入中的所有数字都是十进制的。 
对于 30% 的数据,N ≤ 10; Ma, Mb ≤ 8. 
对于 100% 的数据,2 ≤ N ≤ 1000; 1 ≤ Ma, Mb ≤ 100000; A ≥ B.

输出格式

输出一行一个整数,表示 X 进制数 A − B 的结果的最小可能值转换为十进 制后再模 1000000007 的结果。

输入样例

11
3
10 4 0
3
1 2 0

输出样例

94

样例说明

当进制为:最低位2进制,第二数位5进制,第三数位11进制时,减法得到的差最小。此时A在十进制下是108,B在十进制下是14,差值是94。

#include<iostream>
#include<algorithm>
#include<string>

using namespace std;

const int N = 1e6 + 10;
const int M = 1000000007;
int n, m, x, a[N], b[N], c[N];
long long int sum;

int main()
{
	cin >> x >> n;
	for (int i = n; i >= 1; i--) cin >> a[i];
	cin >> m;
	for (int i = m; i >= 1; i--) cin >> b[i];

	int ma = max(n, m);
	for (int i = ma; i >= 1; i--)
	{
		int maa = max(a[i] + 1, b[i] + 1);
		if (maa > x) maa = x;
		if (maa < 2) maa = 2;
		c[i] = maa;
	}

	for (int i = ma; i >= 2; i--)//最后一项不能加进去c[0]=0
	{
		sum = ((sum + a[i] - b[i] + M) * c[i - 1]) % M;
	}
	sum = (sum + a[1] - b[1]) % M;//最后一项单独计算
	cout << sum << endl;
	return 0;
}

5.1、进制转换思维导图

手工制图,不够更详细,还望各位见谅;

5.2、进制转换思想

  • 首先理解题意真的很重要!很重要!看懂了才有思路!!

  • 和正常的进制转换相比,此题的转换在于不同数位上的进制数不同,而且取决于该数位的大小(进制位是该数位最大数加1,且末位最低为2进制);

  • 要注意相同位数时第一组数减第二组数得到值为负数(例如321&&431中的‘2’减‘3’==‘-1’)(我分享两种方法1.不需要考虑负数2.需要考虑负数);

  • 还要考虑两组数是否有相同的位数(可能存在a为321而b为21这种情况);

  • 关于为什么是乘下一位进制c[i-1],我举一个例子比如说十进制的12(因为只有当个位满了之后才会向十位进一,所以等于1*10+2*1==12);

  • 本题也属于一道贪心题;

5.3、主旨展现

  • 用a数组逆序存第一组数,用b数组逆序存第二组数;(逆序存的目的是为了排除位数不相同的情况)

  • 用c数组存储该位上的进制数;(注意末尾最低也是2进制)

  • 因为可能数值太大,注意运算时要%1000000007;

 6、例题(2)来喽—数制转换—(以10为媒介,y总眼中的小学数奥) 

题目描述

求任意两个不同进制非负整数的转换(2 进制 ∼ 16 进制),所给整数在 int 范围内。

不同进制的表示符号为(0,1,…,9,a,b,…,f)或者(0,1,…,9,A,B…,F)

输入格式
输入只有一行,包含三个整数 a,n,b。a 表示其后的 n 是 a 进制整数,b 表示欲将 a 进制整数 n 转换成 b 进制整数。

a,b 是十进制整数。

数据可能存在包含前导零的情况。

输出格式
输出包含一行,该行有一个整数为转换后的 b 进制数。

输出时字母符号全部用大写表示,即(0,1,…,9,A,B,…,F)。

数据范围
2≤a,b≤16,
给定的 a 进制整数 n 在十进制下的取值范围是 [1,2147483647]。

输入样例:
 

15 Aab3 7


输出样例:
 

210306
#include<iostream>//进制转换
#include<algorithm>
#include<math.h>

using namespace std;
typedef long long LL;

string shu = "0123456789ABCDEF";
LL a, b, sum;
string s, str = "";

int main()
{
	cin >> a >> s >> b;
	LL l = s.size();
	for (int i = 0; i < s.size(); i++)
	{
		if (s[i] >= '0' && s[i] <= '9')
		{
			sum += (s[i] - '0') * pow(a, l - i - 1);
		}
		else if (s[i] >= 'a' && s[i] <= 'f')
		{
			sum += (s[i] - 'a' + 10) * pow(a, l - i - 1);
		}
		else if (s[i] >= 'A' && s[i] <= 'F')
		{
			sum += (s[i] - 'A' + 10) * pow(a, l - i - 1);
		}
	}
	//cout << sum << endl;
	while (sum)
	{
		int x = sum % b;
		str += shu[x];
		sum = sum / b;
	}
	reverse(str.begin(),str.end());
	cout << str << endl;
	return 0;
}

7、例题(3)来喽——数的进制转换——(一道高精度好题)

题目描述

编写一个程序,可以实现将一个数字由一个进制转换为另一个进制。

这里有 62 个不同数位 {0−9,A−Z,a−z}。

输入格式
第一行输入一个整数,代表接下来的行数。

接下来每一行都包含三个数字,首先是输入进制(十进制表示),然后是输出进制(十进制表示),最后是用输入进制表示的输入数字,数字之间用空格隔开。

输入进制和输出进制都在 2 到 62 的范围之内。

(在十进制下)A=10,B=11,…,Z=35,a=36,b=37,…,z=61 (0−9 仍然表示 0−9)。

输出格式
对于每一组进制转换,程序的输出都由三行构成。

第一行包含两个数字,首先是输入进制(十进制表示),然后是用输入进制表示的输入数字。

第二行包含两个数字,首先是输出进制(十进制表示),然后是用输出进制表示的输入数字。

第三行为空白行。

同一行内数字用空格隔开。

输入样例:

8
62 2 abcdefghiz
10 16 1234567890123456789012345678901234567890
16 35 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
35 23 333YMHOUE8JPLT7OX6K9FYCQ8A
23 49 946B9AA02MI37E3D3MMJ4G7BL2F05
49 61 1VbDkSIMJL3JjRgAdlUfcaWj
61 5 dl9MDSWqwHjDnToKcsWE1S
5 10 42104444441001414401221302402201233340311104212022133030

输出样例:

62 abcdefghiz
2 11011100000100010111110010010110011111001001100011010010001

10 1234567890123456789012345678901234567890
16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2

16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
35 333YMHOUE8JPLT7OX6K9FYCQ8A

35 333YMHOUE8JPLT7OX6K9FYCQ8A
23 946B9AA02MI37E3D3MMJ4G7BL2F05

23 946B9AA02MI37E3D3MMJ4G7BL2F05
49 1VbDkSIMJL3JjRgAdlUfcaWj

49 1VbDkSIMJL3JjRgAdlUfcaWj
61 dl9MDSWqwHjDnToKcsWE1S

61 dl9MDSWqwHjDnToKcsWE1S
5 42104444441001414401221302402201233340311104212022133030

5 42104444441001414401221302402201233340311104212022133030
10 1234567890123456789012345678901234567890
#include<iostream>//先将n进制转换为10进制,再讲10进制转换为m进制
#include<algorithm>//由于中间结果可能很大,需要用到高精度运算
#include<string>

using namespace std;

const int N = 1e6 + 10;
int m, x, y, a[N];
string st, s;

int main()
{
	cin >> m;
	while (m--)
	{
		s = "", st = "";
		cin >> x >> y >> st;
		int j = 1;
		for (int i = st.size() - 1; i >= 0; i--)//先将其转化成相对应的十进制数字
		{
			if (st[i] >= '0' && st[i] <= '9') a[j++] = st[i] - '0';
			else if (st[i] >= 'A' && st[i] <= 'Z') a[j++] = st[i] - 'A' + 10;
			else if (st[i] >= 'a' && st[i] <= 'z') a[j++] = st[i] - 'a' + 36;
		}
		int ma = st.size();
		while (ma)/核心代码
		{
			int c = 0;
			for (int i = ma; i >= 1; i--)
			{
				int b = (c * x + a[i]) / y;
				c = (c * x + a[i]) % y;
				a[i] = b;
			}
			while (a[ma] == 0 && ma >= 1) ma--;

			if (c >= 0 && c <= 9) s += char(c + '0');//老是写成(c-'0')
			else if (c >= 10 && c <= 35) s += char(c + 'A' - 10);//老是写成(c-'A'+10)
			else if (c >= 36 && c <= 61) s += char(c + 'a' - 36);//老是写成(c-'a'+36)
		}
		reverse(s.begin(), s.end());//反转函数
		cout << x << " " << st << endl;
		cout << y << " " << s << endl;
		cout << endl;
	}
	return 0;
}

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大小胖虎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值