负进制转换
之前某技术面原题,怎么把一个十进制数12转换为负3进制,今天心血来潮在leetcode搜了下发现确实有原题而且我好像还是不会做的亚子。
传送门如下:
https://leetcode-cn.com/problems/convert-to-base-2/
看明白之后尝试写了一下这个题目的思路:
一般正数的进制转换代码是这样的↓
int trans(int num,int ratio)
{
int res = 0;
int rem = 0;//余数
int i = 0;
while(num!=0)
{
rem = num % ratio;//得到余数
num -= rem;//减去余数之后为除数的整数倍
num /= ratio;//然后得到商
res += rem * pow(10,i);//这里使用的是输出int型,下面LeetCode是因为题目给的返回string,因为都想尝试一下就没有改了。
i++;
}
return res;
}
然后把负进制带进去试了一下,可以发现如果
12/(-3) = -4…0
-4/(-3) = 2…2
2/(-3) = 0…2
因为商为0了所以这个时候停止循环,得到结果就是220,答案正确。
也就是说,如果得到的余数一直都是正数的话,之前的正数进制其实是可以用的。
经过尝试发现m%n取余符号其实是往下取余的,当m为负数时候比如说(-1)%(-2) = 0…-1
而不是(-1)%(-2) = 1…1,也就是让商尽可能小
emm大概这就是负进制的难点了吧
所以,关键步骤就是把余数变为正的!
参考了个大神做法最后得到解答如下:
int main()
{
int N = 12;
string res;//结果
int rem = 0;//余数
int i = 0;
while (N != 0)
{
rem = (N % (-3) + abs(-3)) % (-3);//其实就是说(-1)/(-2)=0...-1的话,那就让它往上取余变成(-1)/(-2)=1....1
N -= rem;
N /= (-3);
res += to_string(rem);
i++;
}
string res_res;
for (int j = 0; j<res.length(); j++)
{
res_res += res[res.length() - 1 - j];
//之前用的res_res[j] = res[res.length() - 1 - j]...然后vs给中断了好多次说数组超了,最后得出结论string还是不要直接赋值好,原理还没搞明白(对的我就是觉得没有啥语法错误。。),希望有懂的小伙伴可以帮个忙
}
cout << res_res;
return 0;
}
输出答案为220,其他进制尝试也没有问题
也算是了了一个心结。