主要内容 #
整数和小数有计算精度的限制。比如:
- unsigned long long 的最大值: 1844 6744 0737 0955 1615 (一千八百多万亿)
- long double 的范围: 1.18973e+4932 ~ 3.3621e-4932
太大的数,或者小数点太多的数,在计算上有限制。就需要使用特殊的处理方法。这就称为高精度计算。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,将这个数字拆开,拆成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。
- 数据的接受和存储
- 高精度位数的确定
- 进位、错位处理
- 4.高精度加法
1. 数据的接收和存贮 #
- 当输入的数很长时,可采用字符串方式输入。
这样可以输入位数很长的数,利用字符串函数和操作运算,将每一位数取出,存入数组中。
因为数组存放的元素顺序与我们计算的顺序是相反的,在竖式计算中我们是将其右对齐(个位对个位,十位对十位,以此类推),而读取数字后的两个数组是左对齐的,因此我们要将里面的元素逆置。
请读入下面的数: 123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789 示例程序: void init() { string s; cin >> s; // 读入字符串 len = s.length(); for(i=0; i <= len; ++i) //逆置元素 a[i]=s[len-1] - '0'; // 将字符转化成数字 }
2. 高精度数位数的确定 #
- 方法:接收时往往是用字符串,所以它的位数就等于字符串的长度。
3. 进位,错位处理 #
下面例程中的 a b c 均为整形数组。
- 加法进位:
c[i] = a[i]+b[i]; if(c[i] >= 10) { c[i] %= 10; ++c[i+1]; }
- 减法借位:
if(a[i] < b[i]) { --a[i+1]; a[i]+=10; } c[i] = a[i]-b[i];
4. 高精度加法 #
请输入两个数,计算它们的和。
【算法分析】
竖式方法举例:962+93
【例程】
#include < iostream > #include < string > using namespace std; //高精度加法函数 void add(int a[], int a_len, int b[], int b_len, int* result, int& result_len) { int i = 0, x = 0; result_len = 0; int max_a_b = a_len > b_len ? a_len : b_len; while (i< max_a_b) { int sub_a = i < a_len ? a[i] : 0; //判断i是否超过数组a的长度,若超过该位为0 int sub_b = i < b_len ? b[i] : 0; //判断i是否超过数组b的长度,若超过该位为0 result[i] = sub_a + sub_b + x;//逐位相加 x = result[i] / 10; result[i] %= 10; result_len++; i++; } if (x != 0) { result[i] = x; ++result_len; } } int main() { string astr, bstr; cin >> astr; cin >> bstr; int lena = astr.size(), lenb = bstr.size(); int a[100], b[100]; for (int i = 0; i< lena; ++i) a[lena - i - 1] = astr[i] - '0'; // 将数字倒过来,并转化成数字 for (int i = 0; i< lenb; ++i) b[lenb - i - 1] = bstr[i] - '0'; int c[100] = { 0 }, lenc=0; add(a, lena, b, lenb, c, lenc); // 计算 for (int i = 0; i < lenc; ++i) { cout << c[lenc - i - 1]; // 再将数字倒过来输出 } cout << endl; return 0; }
习题 #
请将上面的例题,独立完成一遍。要求必须掌握。下节课要求每个人都能够独立写出上面的代码。
课后练习