让N进制数转化为M进制数

1.N进制-10进制-M进制

常规方法可以用短除法取余数再倒序输出的方法来,但这一方法实际上为N进制-10进制-M进制。


2.C++自带函数 strtol()

strtol():可以把任一进制的字符串转成long。用法:strtol(字符串,NULL,要转的进制),返回值就是结果。

strtol,strtoll介绍

但是把int转成别的进制字符串有些困难,因此需要使用函数把int转化成任一进制的字符串

windows下有个现成的itoa()函数 用法:itoa(要转的值,字符串,目标进制) itoa(strtol(s,NULL,b),t,m)

std::iota介绍

Linux下可用to_chars()函数 用法:to_chars(字符串,字符串尾部指针,要转的值,目标进制) to_chars(t,t+40,strtol(s,NULL,b),m);

std::to_chars, std::to_chars_result 介绍

还有一个问题,就是这样转出来的字符串是小写的,题目要求是大写。这好像没有现成的函数可以做,需要用<locale>中的toupper函数

auto& f=use_facet<ctype<char>>(locale());
    f.toupper(t,t+40);

P1143 进制转换 - 洛谷

题目描述

请你编一程序实现两种不同进制之间的数据转换。

输入格式

共三行,第一行是一个正整数,表示需要转换的数的进制n(2≤n≤16),第二行是一个n进制数,若n>10则用大写字母A-F表示数码10-15,并且该n进制数对应的十进制的值不超过1000000000,第三行也是一个正整数,表示转换之后的数的进制m(2≤m≤16)。

输出格式

一个正整数,表示转换之后的m进制数。

样例 #1

样例输入 #1

16
FF
2

样例输出 #1

11111111

解法1:

用栈的特性逆顺序输出,也可用递归的方式

#include<bits/stdc++.h>
#include<iostream>
using namespace std;
unsigned long long num = 0;
int n, k;
stack<char>q;
void solve() {
    int jinzhi1, jinzhi2;
    cin >> jinzhi1;
    string str;
    cin >> str;
    for (int i = 0; i < str.length(); i++) {
        num *= jinzhi1;
        if (str[i] < 'A') {
            num += str[i] - '0';
        }
        else {
            num += 10 + (str[i] - 'A');
        }
    }
    cin >> jinzhi2;
    while (num >= jinzhi2) {
        if (num % jinzhi2 < 10) {
            q.push('0' + num % jinzhi2);
            num /= jinzhi2;
        }
        else {
            q.push('A' + (num % jinzhi2 - 10));
            num /= jinzhi2;
        }
        if (num < jinzhi2) {
            q.push('0' + num);
        }
    }
    while (!q.empty()) {
        cout << q.top();
        q.pop();
    }
    return;
}
int main() {
    solve();
    return 0;
}

解法2:

用C++自带函数写

*需要了解测评机的运行环境是Windows还是Linux

#include<bits/stdc++.h>
#include<iostream>
using namespace std;
int b,m;char s[40],t[40];
int main(){
    scanf("%d %s %d",&b,s,&m);
    to_chars(t,t+40,strtol(s,NULL,b),m);
    //如果把上面一行改成itoa(strtol(s,NULL,b),t,m),应该就能使用Dev-C++,C++11编译通过
    auto& f=use_facet<ctype<char>>(locale());
    f.toupper(t,t+40);
    puts(t);
    return 0;
}

参考:题解 P1143 【进制转换】

负进制数转化

让N进制数转化为M进制数

方法与上面的1相同,转化过程为N进制-10进制-M进制

但区别在于

已知:被除数=商*除数+余数

例如在C++里,-15%-2=-1,-15/-2=7,而7*-2+(-1)=-15

但是因为我们是不断取余数倒序为转换结果,所以余数不能出现负数,那怎么办呢?

我们只需要将商+1,余数-除数即可,因为余数(绝对值)一定小于除数,所以这样就可以将余数装换为正数

正确性证明:

(商+1)*除数+(余数-除数)=商*除数+除数+余数-除数=商*除数+余数=被除数

参考:题解 P1017 【进制转换】 负进制数_百度百科 (baidu.com)


NOIP2000 提高组 进制转换

题目描述

我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置为指数,以 10 为底数的幂之和的形式。例如 123 可表示为 1 \times 10^2+2\times 10^1+3\times 10^0 这样的形式。

与之相似的,对二进制数来说,也可表示成每个二进制数码乘以一个以该数字所处位置为指数,以 2 为底数的幂之和的形式。

一般说来,任何一个正整数 R 或一个负整数 -R 都可以被选来作为一个数制系统的基数。如果是以 R 或 -R 为基数,则需要用到的数码为 0,1,....R-1。

例如当 R=7 时,所需用到的数码是 0,1,2,3,4,5,6,这与其是 R 或 -R 无关。如果作为基数的数绝对值超过 10,则为了表示这些数码,通常使用英文字母来表示那些大于 9 的数码。例如对 16 进制数来说,用 A 表示 10,用 B 表示 11,用 C 表示 12,以此类推。

在负进制数中是用 -R 作为基数,例如 -15(十进制)相当于 110001 (-2进制),并且它可以被表示为 2 的幂级数的和数:

110001=1\times (-2)^5+1\times (-2)^4+0\times (-2)^3+0\times (-2)^2+0\times (-2)^1 +1\times (-2)^0

设计一个程序,读入一个十进制数和一个负进制数的基数, 并将此十进制数转换为此负进制下的数。

输入格式

输入的每行有两个输入数据。

第一个是十进制数 n。 第二个是负进制数的基数 -R。

输出格式

输出此负进制数及其基数,若此基数超过 10,则参照 16 进制的方式处理。

样例 #1

样例输入 #1

30000 -2

样例输出 #1

30000=11011010101110000(base-2)

样例 #2

样例输入 #2

-20000 -2

样例输出 #2

-20000=1111011000100000(base-2)

样例 #3

样例输入 #3

28800 -16

样例输出 #3

28800=19180(base-16)

样例 #4

样例输入 #4

-25000 -16

样例输出 #4

-25000=7FB8(base-16)

提示

【数据范围】 对于 100\% 的数据,-20 \le R \le -2,|n| \le 37336。


题解:

还是用了栈来进行倒序输出

#include<bits/stdc++.h>
#include<iostream>
using namespace std;
typedef long long ll;
stack<char>s;
void solve() {
    int n, k;
    cin >> n >> k;
    cout << n<<"=";
    while (n!=0) {
        int x = n % k;
        if (x < 0) {//关键于此
            x -= k;
            n += k;
        }
        if (x < 10) s.push('0' + x);
        else s.push('A' + x - 10);
        n /= k;
    }
    while (!s.empty()) {
        cout << s.top(); s.pop();
    }
    cout << "(base" << k << ")";
    return;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
    return 0;
}