数及其运算
自然数/整数/有理数/实数及其运算
【略】
进制与进制转换
进制的表示
进制就是进位计数制,是一种带进位的计数方法。
我们平时生活当中所使用的数字系统是十进制的,而计算机内部是使用二进制来表示的,除此之外,还有一些其它的进制,比如时间中的时、分、秒,用的是六十进制,在 C++ 中,变量的内存地址是用十六进制表示的(如:0x7ffde284d5a4
,其中 0x 代表十六进制),网页里的颜色表示很多时候用的也是十六进制(如:#FF0000
代表红色)。
下面是常见的四种进制及其表示。
进制 | 基数 | 进位条件 | 组成数字/字符 |
---|---|---|---|
二进制(B) | 2 | 逢 2 进 1 | 0 和 1,共 2 个数字 |
八进制(O) | 8 | 逢 8 进 1 | 0 ~ 7,共 8 个数字 |
十进制(D) | 10 | 逢 10 进 1 | 0 ~ 9,共 10 个数字 |
十六进制(H) | 16 | 逢 16 进 1 | 0 ~ 9,A ~ F,共 16 个字符 |
根据需求,不同进制之间是可以相互转换的,大致可分为下面两大类:
- 十进制与其它 进制之间的相互转换
- 二、八、十六进制之间的相互转换
下面我们一起来看看。
十进制转 进制
这里以十进制转二进制为例,可以将十进制数划分为整数部分和小数部分(若没有小数部分则省略)。整数部分采用除二取余法,小数部分采用乘二取整法。
例如,要将二进制数 26.3125 转换为二进制数,分别用除二取余法和乘二取整数转换整数和小数部分。
除二取余法
就是用 2 连续去除十进制整数,直到商为 0 为止,最后将余数逆序输出即可得到该十进制数所对应的二进制数表示。
为了方便,用 来表示该数是十进制表示, 表示的该数为二进制表示。
例如,下图是用除二取余法将整数部分 26 转换为二进制的过程。
因此整数部分十进制 的二进制表示为 。
同样道理,如果要将十进制转换为其它的 进制,只需要除 取余,直到商为 0,逆序输出余数即可。
乘二取整法
用 2 连续去乘十进制数,将得到的积的整数取出,继续用 2 去乘余下的小数部分,如此循环,直到得到的积的小数部分为 0 为止,最后将每次取出的整数部分按顺序排列并输出,就可以得到小数的二进制表示。
有的小数在用乘二取整法转换时,会无限运算下去,所以根据需要的精度取足够的位数即可停止计算。
下图是用乘二取整法将小数部分 0.3125 转换为二进制的过程。
同样道理,如果要将十进制转换为其它的 进制,只需要乘 取整,直到积的小数部分为 0,按顺序序输出每次的整数部分即可。
需要注意的是,很多浮点数都无法用二进制来精确表示,比如说
0.1
,正因为如何,才会出现 ` 这个问题出现,甚至有专门的一个 Floating Point Math 网站 来记录在不同语言中这个问题的情况,感兴趣的同学可以去看看。
十进制转二进制代码实现
代码实现有两个关键的部分。
1. 除二取余的实现
这部分与之前学过的十进制数字拆分完全一致,配合应用用 %
与 /
运算即可实现。
2. 逆序输出的实现
有两种方法实现逆序输出。
- 数组方法:将每次得到的余数存入一个数组,运算完成后,将数组逆序输出。
- 字符串拼接方法:利用字符拼接的先后顺序来实现逆序输出。
通过数组方法逆序输出,代码如下:
#include <iostream>using namespace std;
const int N = 100; // 最长的二进制位数int q[N];
int main() { int n; cin >> n;
int k = 0; // 用于计位数 while (n > 0) { q[k] = n % 2; n = n / 2; k++; }
// 逆序输出,得到转换后的二进制数 for (int i = k - 1; i >= 0; i--) { cout << q[i]; }
return 0;}
通过字符串拼接输出,代码如下:
#include <iostream>using namespace std;
int main() { int n; cin >> n; string s = "";
while (n > 0) { int t = n % 2; char c = t + '0'; // 将数字转换为对应的字符 s = c + s; // 将字符 c 放在前面拼接,实现最终的倒序 n /= 2; }
cout << s << endl; return 0;}
十进制转十六进制代码实现
十进制转十六进制稍微要麻烦一点,因为十六进制数中还包括对字母 ~ 的表示和处理。
实现代码如下:
#include <iostream>using namespace std;
int main() { int n; cin >> n; char c; string s = "";
while (n > 0) { int t = n % 16; //分别处理数字与字母的对应关系 if (t < 10) { c = t + '0'; } else { c = t + 'A' - 10; } s = c + s; // 利用字符串拼接逆序输出 n /= 16; // 十六进制应该除以 16 }
if (s == "") cout << 0; else cout << s;
return 0;}
进制转十进制
一个十进制的数字, (其中 表示数字中的一位),可以表示为:
举例来说,对于十进制数 可以表示为(加权展开):
实际上,一个 进制的数字,遵循同样的规则,可以按加权求和的方式来得到对应的十进制数。
例如,对于二进制数 ,可以表示为:
对于一个 进制数,用数字乘以对应数字位上的位权(不同的进制,位权不同),求和即可得到对应的十进制数。
二进制转十进制代码实现
下面以二进制数转十进制为例,代码实现如下:
// 二进制转十进制,加权求和#include <iostream>using namespace std;
int main() { int n; cin >> n;
int t = 1, sum = 0; while (n > 0) { sum = sum + (n % 10) * t; // 拆开数字,加权求和 n = n / 10; t = t * 2; }
cout << sum << endl; return 0;}
十六进制转十进制代码实现
因为十六进制数含有字母,在输入时,以字符串来输入,在转换时需要考虑到对应字母的转换。其它的部分与二进制转十进制的逻辑是一致的。
#include <iostream>using namespace std;
int main() { string s; cin >> s;
int t = 1, sum = 0;
for (int i = s.size() - 1; i >= 0; i--) { if (isdigit(s[i])) { sum = sum + (s[i] - '0') * t; } else { sum = sum + (s[i] - 'A' + 10) * t; } t = t * 16; }
cout << sum << endl; return 0;}