主要内容 #
- 高精度除以单精度例题精讲
- 高精度除以高精度例题精讲
1. 高精度除以单精度例题精讲 #
1.1 计算过程 #
1.输入大整数的数字串和整数b。用string存储大整数的数字串,用int存储整数b
2.将数字串从低位往高位存储到数组a中
3.利用竖式计算,c=a/b
(1)首先,另余数为x=0;
(2)让余数乘以10,和高位的第一个位置的数相加,然后除以b,得到此位置的商;
(3)求出此时的余数x;
(4)接着往高位的下一位走,重复(2)(3)步骤,直到最后一位;
4.输出商和余数
1.2 例题 #
一个大整数除以一个整数(低精度数)
输入:
一个大于0的大整数a,长度不超过100位,求出除以一个整数b。
输出:l
一行,商和余数,中间用空格隔开。
样例输入:
2132104848488485 13
样例输出:
164008065268345 0
参考程序
#include < iostream > #include < string > using namespace std; const int MAX = 101; int main(int argc, const char * argv[]) { int b, i, la, lc, x; string str; int a[MAX], c[MAX]; while(cin >> str >> b) { // 1.输入大整数和整数b memset(a, 0, sizeof(a)); // 清零 memset(c, 0, sizeof(c)); // 获取大整数的长度 la = (int)str.size(); for(i = 0; i < la; i++) a[la-i-1] = str[i] - '0'; // 2.将数字串从低位往高位存储到数组a中 // 3.计算c=a/b x = 0; // 余数初始为0 for(i = la-1; i >= 0; i--) { c[i] = (x * 10 + a[i]) / b; // 将高位得到的余数乘以10,再加上新位置的数,再除以b x = (x * 10 + a[i]) % b; // 得出余数 } lc = la; while(lc > 1 && c[lc-1] == 0) // 4.删去多余的0 lc--; // 5.从高位往低位输出商 for(i = 0; i < lc; i++) cout << c[lc-i-1]; // 空格输出余数 cout << " " << x << endl; } return 0; }
2. 高精度除以高精度例题精讲 #
2.1 计算过程 #
基本思想是反复做减法,看看从被除数里最多
能减去多少个除数,商就是多少。
• 一个一个减显然太慢,如何减得更快一些呢?
• 以7546除以23为例来看一下:开始商为0
– 先减去23的100倍,就是2300,发现够减3次,余下646。于是商的值就增加300
– 然后用646减去230,发现够减2次,余下186。于是商的值增加20,变为320
– 最后用186减去23,够减8次,因此最终商就是328
• 本题的核心是要写一个大整数的减法函数,然后反复调用该函数进行减法操作。
2.2 例题 #
两个大整数相除
输入:
两行,分别是被除数和除数。
输出:l
两行,商和余数。
样例输入:
2132104848488485
13
样例输出:
164008065268345
0
参考程序
#include < iostream > #include < string > using namespace std; int Substract(int nMaxLen, int *an1, int * an2) //大整数an1减去an2。两者最多nMaxLen位,an1必须不小于an2, 差放在an1里 //返回差的最高非0位的位置 { int i, nStartPos = 0; for ( i = 0; i < nMaxLen ; i ++ ) { an1[i] -= an2[i]; //逐位相减 if ( an1[i] < 0 ) { //看是否要借位 an1[i] += 10; an1[i+1] --; //借位 } if ( an1[i] ) nStartPos = i; //记录最高位的位置 } return nStartPos; } int Length(int nMaxLen, int *an) // 求大整数的位数,0算0位 { int i; for ( i = nMaxLen - 1; an[i] == 0 && i >= 0; i-- ); if ( i >= 0 ) return i + 1; return 0; } void ShiftLeft(int nMaxLen, int *an1, int *an2, int n) // 将大整数an1左移n位,即乘以10的n次方,结果放到an2里 { int i; memcpy(an2, an1, nMaxLen * sizeof(int)); if ( n <= 0 ) return; for ( i = nMaxLen -1; i >= 0; i -- ) { // 请写出循环体代码 if(i - n >= 0) an2[i] = an1[i - n]; } for(int j = 0; j < n; ++j){ an2[j] = 0; } } int * Max(int nMaxLen, int *an1, int *an2) // 求大整数an1和an2里面大的那个;若an1==an2,返回an1 // 如果都是0,则返回NULL { bool bBothZero = true; int i; for ( i = nMaxLen -1; i >= 0 ; i -- ) { if ( an1[i] > an2[i] ) return an1; else if ( an1[i] < an2[i] ) return an2; else if ( an1[i] ) bBothZero = false; } if ( bBothZero) return NULL; else return an1; } #define MAX_LEN 110 int an1[MAX_LEN]; // 存放被除数, an1[0]对应于个位 int an2[MAX_LEN]; // 存放除数 int tmpAn2[MAX_LEN]; int anResult[MAX_LEN];//存放商 string szLine1;//存放被除数的字符串 string szLine2;//存放除数的字符串 int main() { int n = 1; while(n--) { cin >> szLine1; cin >> szLine2; int i, j; //库函数memset将地址an1开始的sizeof(an1)字节内容置成0 memset(an1, 0, sizeof(an1)); memset(an2, 0, sizeof(an2)); //下面将szLine1中存储的字符串形式的整数转换到an1中去, int nLen1 = szLine1.size(); for (j = 0, i = nLen1 - 1; i >= 0; i--) an1[j++] = szLine1[i] - '0'; int nLen2 = szLine2.size(); for ( j = 0, i = nLen2 - 1; i >= 0; i--) an2[j++] = szLine2[i] - '0'; int nHighestPos = 0; memset(anResult, 0, sizeof(anResult)); int nShiftLen = Length(MAX_LEN, an1) - Length(MAX_LEN, an2); // 只要an1大于an2,就不停相减 while( Max(MAX_LEN, an1, an2) == an1 ) { // 算出an2的10的nShiftLen次方倍 ShiftLeft(MAX_LEN, an2, tmpAn2, nShiftLen); // 重复减去an2的10的nShiftLen次方倍,看能减几次 while( Max(MAX_LEN, an1, tmpAn2) == an1) { Substract(MAX_LEN, an1, tmpAn2); anResult[nShiftLen] ++; // 记录商对应位 } // 记录结果最高位的位置 if( nHighestPos == 0 && anResult[nShiftLen]) nHighestPos = nShiftLen; nShiftLen--; } for ( i = nHighestPos; i >= 0; i-- ) cout << anResult[i]; cout << endl; int k = MAX_LEN - 1; //去除余数的前导0 while(k >=0 && an1[k] == 0) --k; //整除,余数为0 if(k == -1) cout << 0; else for(k; k >= 0; --k) cout << an1[k]; cout << endl; } return 0; }