本文将简单的讨论非负整数的N
进制与十进制之间如何进行转换。
一、十进制与二进制的表示
先来看十进制数的表示,数n
的十进制可以分解为n = d[0] + d[1] * 10 + d2 * 10^2 + …… + d[k] * 10^k
,其中0 <= d[i] < 10
,例如12345 = 5 + 4 * 10 + 3 * 10^2 + 2 * 10^3 + 1 * 10^4
,也就是d[0] = 5, d[1] = 4, d[2] = 3, d[3] = 2, d[4] = 1
,数n
的十进制表示为d[k]d[k-1]……d[1]d[0]
,对于上述例子即12345
。
同样地,数m
的二进制可以表示为m = b[0] + b[1] * 2^1 + …… + b[k] * 2^k
,其中0 <= b[i] < 2
,例如7 = 1 + 1 * 2^1 + 1 * 2^2
,也就是b[0] = 1, b[1] = 1, b[2] = 1
,数m
的二进制表示为b[k]b[k-1]……b[1]b[0]
,对于上述例子即111
。
二、十进制转换成二进制
思考一下,对于一个数,我们是如何求它十进制对应的每一位?例如n = 9527
,我们通过n % 10
求得个位上的数是9527 % 10 = 7
,然后令n = n / 10
(取整除部分),重复n % 10
和n = n / 10
这个过程即可得到十位、百位、千位的数字分别为2
、5
、7
。把每一位合起来就是该数的十进制表示。
同样的,对于一个数,我们可以通过上述方法求它二进制对应的每一位。假设对于数字m
,通过m % 2
即可求得它的个位,然后令m = m / 2
,继续上述过程即可求得十位、百位、……等等。举个例子来说m = 11
,那么个位为m % 2 = 1
,令m = m / 2 = 11 / 2 = 5
,那么十位为m % 2 = 5 % 2 = 1
,即十位为1
,继续令m = m / 2 = 5 / 2 = 2
,那么百位为m % 2 = 2 % 2 = 0
,即百位为0
,继续令m = m / 2 = 2 / 2 = 1
,那么千位为m % 2 = 1 % 2 = 1
,即千位为1
,此时m = m / 2 = 1 / 2 = 0
,到此转换结束,因此最终的二进制表示为1011
。
C++
示例代码如下:
// Conver.h
#include <string>
namespace Convert {
std::string DecimalToBinary(unsigned int d);
};
// Conver.cpp
#include <string>
namespace Convert {
std::string DecimalToBinary(unsigned int d)
{
if (d == 0) {
return "0";
}
std::string result;
while (d > 0) {
result += ('0' + d % 2);
d /= 2;
}
std::reverse(result.begin(), result.end());
return result;
}
};
// test.cpp
#include <iostream>
#include "Convert.h"
int main(int argc, char **argv)
{
std::cout << "0 to binary is: " << Convert::DecimalToBinary(0) << std::endl;
std::cout << "1 to binary is: " << Convert::DecimalToBinary(1) << std::endl;
std::cout << "2 to binary is: " << Convert::DecimalToBinary(2) << std::endl;
std::cout << "10 to binary is: " << Convert::DecimalToBinary(10) << std::endl;
std::cout << "16 to binary is: " << Convert::DecimalToBinary(16) << std::endl;
std::cout << "9527 to binary is: " << Convert::DecimalToBinary(9527) << std::endl;
return 0;
}
// 执行结果
0 to binary is: 0
1 to binary is: 1
2 to binary is: 10
10 to binary is: 1010
16 to binary is: 10000
9527 to binary is: 10010100110111
三、二进制转换为十进制
思考一下,对于十进制表示的数n = d[3]d[2]d[1]d[0]
,我们如何求得它的结果?很显然是:(((d[3] * 10) + d[2]) * 10 + d[1]) * 10) + d[0]
。那么对于二进制表示的数m = b[3]b[2]b[1]b[0]
,同样可得到它的结果为(((b[3] * 10) + b[2]) * 10 + b[1]) * 10) + b[0]
。因为在我们当前的运算体系中,都是以十进制来表示的,所以对于(((d[3] * 10) + d[2]) * 10 + d[1]) * 10) + d[0]
和(((b[3] * 10) + b[2]) * 10 + b[1]) * 10) + b[0]
得到的都是以十进制表示的结果。那么对于二进制转换为十进制,C++
代码如下:
// Conver.h
#include <string>
namespace Convert {
unsigned int BinaryToDecimal(const std::string &b);
};
// Conver.cpp
#include <string>
namespace Convert {
unsigned int BinaryToDecimal(const std::string &b)
{
if (b.size() == 0) {
return 0;
}
unsigned int result = 0;
for (const auto &c : b) {
result = result * 2 + (c - '0');
}
return result;
}
};
// test.cpp
#include <iostream>
#include "Convert.h"
int main(int argc, char **argv)
{
std::cout << "null to decimal is: " << Convert::BinaryToDecimal("") << std::endl;
std::cout << "0 to decimal is: " << Convert::BinaryToDecimal("0") << std::endl;
std::cout << "1 to decimal is: " << Convert::BinaryToDecimal("1") << std::endl;
std::cout << "10 to decimal is: " << Convert::BinaryToDecimal("10") << std::endl;
std::cout << "1000 to decimal is: " << Convert::BinaryToDecimal("1000") << std::endl;
std::cout << "1100101 to decimal is: " << Convert::BinaryToDecimal("1100101") << std::endl;
return 0;
}
// 执行结果
null to decimal is: 0
0 to decimal is: 0
1 to decimal is: 1
10 to decimal is: 2
1000 to decimal is: 8
1100101 to decimal is: 101
四、数的任意进制表示
在前面的描述中,是把数
和数的进制表示
做了区分的。数
更像是一个客观存在的概念,而数的进制表示
则只是这个数
在某个进制
上的外在表现形式,不管是以何种进制来表示这个数,数的大小都是客观不变且一致的。
那么对于一个数m
的N
进制我们该如何表示?按照本文的第一节,我们可以写成m = d[0] + d[1] * N^1 + d[2] * N^2 + …… + d[k] * N^k
;因此,d[k][d[k-1]……d[1]d[0]
即为数m
的N
进制表示(注意要满足0 <= d[i] < N
)。
- 将十进制转换成
N
进制数。我们可以通过如下两步来得到数m
的N
进制表示:
- 初始时
i = 0
; - 令
d[i] = m % N
; - 令
m = m / N
; - 令
i = i + 1
,并重复步骤2~步骤4,直到m == 0
; -
d[k]d[k-1]……d[1]d[0]
即为m
的N
进制表示。
为了演示简单,此处假设2 <= N <= 10
,C++
代码如下:
// Conver.h
#include <string>
namespace Convert {
std::string DecimalToBaseN(unsigned int d, int convertBase);
};
// Conver.cpp
#include <string>
namespace Convert {
std::string DecimalToBaseN(unsigned int d, int convertBase)
{
if (d == 0 || convertBase < 2 || convertBase > 10) {
return "0";
}
std::string result;
while (d > 0) {
result += ('0' + d % convertBase);
d /= convertBase;
}
std::reverse(result.begin(), result.end());
return result;
}
};
// test.cpp
#include <iostream>
#include "Convert.h"
int main(int argc, char **argv)
{
std::cout << "15 to base-2 is: " << Convert::DecimalToBaseN(15, 2) << std::endl;
std::cout << "15 to base-3 is: " << Convert::DecimalToBaseN(15, 3) << std::endl;
std::cout << "15 to base-4 is: " << Convert::DecimalToBaseN(15, 4) << std::endl;
std::cout << "15 to base-5 is: " << Convert::DecimalToBaseN(15, 5) << std::endl;
std::cout << "15 to base-6 is: " << Convert::DecimalToBaseN(15, 6) << std::endl;
std::cout << "15 to base-7 is: " << Convert::DecimalToBaseN(15, 7) << std::endl;
std::cout << "15 to base-8 is: " << Convert::DecimalToBaseN(15, 8) << std::endl;
std::cout << "15 to base-9 is: " << Convert::DecimalToBaseN(15, 9) << std::endl;
std::cout << "15 to base-10 is: " << Convert::DecimalToBaseN(15, 10) << std::endl;
return 0;
}
// 执行结果
15 to base-2 is: 1111
15 to base-3 is: 120
15 to base-4 is: 33
15 to base-5 is: 30
15 to base-6 is: 23
15 to base-7 is: 21
15 to base-8 is: 17
15 to base-9 is: 16
15 to base-10 is: 15
- 将
N
进制转换成十进制,可以通过如下步骤来得到:
- 假设
N
进制的数表示为d[k]d[k-1]……d[1]d[0]
,初始时i = k
,转换结果存储在result
中; -
result = result * N + (d[i] - '0')
; - 令
i = i - 1
,重复步骤2~步骤3,当i < 0
时,转换终止。 -
result
即为转换后的结果。
同样也假设2 <= N <= 10
,C++
代码如下:
// Conver.h
#include <string>
namespace Convert {
unsigned int BaseNToDecimal(const std::string &bn, int convertBase);
};
// Conver.cpp
#include <string>
namespace Convert {
unsigned int BaseNToDecimal(const std::string &bn, int convertBase)
{
if (bn.size() == 0) {
return 0;
}
unsigned int result = 0;
for (const auto &c : bn) {
result = result * convertBase + (c - '0');
}
return result;
}
};
// test.cpp
#include <iostream>
#include "Convert.h"
int main(int argc, char **argv)
{
std::cout << "Base-2 1111 to decimal is: " << Convert::BaseNToDecimal("1111", 2) << std::endl;
std::cout << "Base-3 120 to decimal is: " << Convert::BaseNToDecimal("120", 3) << std::endl;
std::cout << "Base-4 33 to decimal is: " << Convert::BaseNToDecimal("33", 4) << std::endl;
std::cout << "Base-5 30 to decimal is: " << Convert::BaseNToDecimal("30", 5) << std::endl;
std::cout << "Base-6 23 to decimal is: " << Convert::BaseNToDecimal("23", 6) << std::endl;
std::cout << "Base-7 21 to decimal is: " << Convert::BaseNToDecimal("21", 7) << std::endl;
std::cout << "Base-8 17 to decimal is: " << Convert::BaseNToDecimal("17", 8) << std::endl;
std::cout << "Base-9 16 to decimal is: " << Convert::BaseNToDecimal("16", 9) << std::endl;
std::cout << "Base-10 15 to decimal is: " << Convert::BaseNToDecimal("15", 10) << std::endl;
return 0;
}
// 执行结果
Base-2 1111 to decimal is: 15
Base-3 120 to decimal is: 15
Base-4 33 to decimal is: 15
Base-5 30 to decimal is: 15
Base-6 23 to decimal is: 15
Base-7 21 to decimal is: 15
Base-8 17 to decimal is: 15
Base-9 16 to decimal is: 15
Base-10 15 to decimal is: 15
五、结束
前面讨论的非负整数的10
进制以内的N
进制与10
进制互相转换,有几个扩展问题可以思考一下:
- 对于负整数,转换过程有何区别?
- 对于大于
10
进制的转换,该如何处理? - 对于
N
进制与M
进制互相转换,该如何处理?