上一篇我们描述了:高精度是什么?如何表示高精度?
我们知道高精度是用来表示数字的。既然是数字,那么我们会想到使用数字来进行运算。比如说,加法,减法,乘法,除法等。我们依次来介绍吧。
在具体介绍加减乘除之前,我想我们还是非常有必要了解一下高精度数字的输入输出方式。
高精度数字是如何输入的?
很显然,高精度的数字是超过long long
的表示范围的。因此我们并不能使用任何现有类型的变量直接存储。我们上一篇提供的方式是使用整数一维数组来存放高精度数字。输入时,我们也采用输入数组一样的方式吗?
int arr[100] ={};
for(int i = 0;i < 100; ++i)
cin >> arr[i];
显然这种方法是不切实际的。我们并不知道数字的实际长度,并且在这个代码中,我们需要输入一百个数字才可以,还需要使用空格隔开——cin
会跳过空格。你可能会直接输入5679293234813203422432
这样的数字,这是不允许的。由于数字之间没有空格,程序会当成一个数字。int
类型是没办法保存这么大的数字的。这会使程序出错。
解决方法就是使用字符串——string
类型可以很好地解决这个问题。
string
类型是C++
的标准类型,它专门用来存放字符串,并且最大的优势是string
类型可以自动推断字符串长度——使用size()
函数就可以获得。
string s;
cin >> s;
我们可以使用56793234813203422432
进行测试,答案是没问题的。字符串s
中保存着这个数字。但这与我们想要的整数数组并不相同。我们需要的是一个个位数字在下标为0
处的整数数组。
下标 | 0 | 1 | 2 | 3 | 4 | … | s.size()-3 | s.size()-2 | s.size()-1 |
---|---|---|---|---|---|---|---|---|---|
输入的形式 | ‘5’ | ‘6’ | ‘7’ | ‘9’ | ‘3’ | … | ‘4’ | ‘3’ | ‘2’ |
想要的形式 | 2 | 3 | 4 | … | … | … | 7 | 6 | 5 |
这两个是由差别的。
1.输入的字符串中每一个元素都是字符
。
2.想要的结果应该是个位数字在下标为0
的位置。
针对第一个问题,我们需要将字符
转化为数字
,这相对于简单。
char ch = '0';
int num = ch - '0'; //‘0’在ASCII编码中为48,字符数字减去‘0’以后,便可以得到正常的数字
//例如:'1' --> 1
ch = '1'; //ASCII码为49
num = ch - '0'; //49 - 48 = 1 得到数字1
对于第二个问题,我们就需要观察上述表格。'5'
在输入形式中下标为0
,而5
则处于s.size()-1
的位置。那么我们可以说这两个位置对应。同样地,'6'
在输入形式中下标为1
,而6
则处于s.size()-1-1
的位置——这里我故意写成两个-1
,这样更好地寻找规律。
规律发现了吗?当某一个字符ch
处于输入形式中下标为i
的位置时,则当它转化为逆向的整数数组时,它的位置处于s.size()-1-i
的位置。
有了这个规律,我们就方便多了。
string s;
cin >> s;
int sArr[100] = {}; //s字符串转换之后存放在sArr中
for(int i = 0;i < s.size(); ++i)
sArr[i] = s[s.size() - 1 - i] - '0'; //减去'0'是转换成数字,而非字符
现在,终于处理好了输入的内容。对于sArr
这样的一个数组,其中有100
个元素,前面部分是我们保存的数字,后面部分(超过s.size()
的部分)是0
,由默认初始化得到的。
下标 | 0 | 1 | 2 | 3 | … | s.size()-3 | s.size()-2 | s.size()-1 | s.size() | … | 97 | 98 | 99 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
高精度数字 | 2 | 3 | 4 | … | … | 7 | 6 | 5 | 0 | … | 0 | 0 | 0 |
现在我们要把他们输出出来。很显然,我们需要从s.size()-1
的位置开始,不断向左,直到下标为0
。但如果我们只能看到sArr
这个数组时,我们就不能用s.size()-1
进行运算了。例如下面这种情况。
#include <iostream>
using namespace std;
void add(int sArr[])
{
//在这个函数中使用sARr数组,它是由主函数中的sArr传递进来
}
int main()
{
string s;
cin >> s;
int sArr[100] = {};
for(int i = 0;i < s.size(); ++i)
sArr[i] = s[s.size() - 1 - i] - '0';
add(sArr); //调用函数
return 0;
}
对于这种情况,我们该怎么办呢?
我们可以去前导零的方式获取。我们选择从100-1
开始,这是最大的下标。当该元素为0
时,我们可以一直减少下标,直到第一个非零数字出现。同样地,我们举例来看。
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
数组元素 | 4 | 0 | 6 | 4 | 0 | 0 | 0 |
在这个表格中,就很清晰了。从下标6
开始,数组元素是0
。因此我们需要减少下标的值。此时,下标为5
,数组元素仍为0
。还需要减少下标的值。此时,下标为4
,数组元素为0
。继续减少下标的值。下标值为3
,数组元素为4
,不再是0
。从这个位置开始,一直到下标为0
,都是我们需要输出的内容。
//假设数组sArr已经定义好,并完成了高精度数字的转化
//int sArr[100] = {};
int k = 100 - 1; //100个元素,下标最大为100-1
//解释:k > 0是必须的。
//当数组中全部都是0时,我们认为这个数组保存的高精度数字是0,我们应该输出0
while(sArr[k] == 0 && k > 0) //当sArr中下标为k时,一直减少。
--k;
经过这样的操作,关于高精度数字的输入输出我们就介绍完成了。