由于编程语言提供的基本数值数据类型表示的数值范围有限,不能满足较大规模的高精度数值计算,因此需要利用其他方法实现高精度数值的计算。
实现高精度数值计算,虽然不能利用编程语言提供的基本数值数据类型,但是可以利用字符串存储高精度数,计算的结果同样保存在字符串中,将高精度数运算转化为字符串运算。以下列举出高精度数相关运算。
1.大数加法
- /*
- * 高精度数
- * 结果存储在字符串a中,字符串a初始为0
- * 计算结束,将字符串a翻转即为高精度数a,b的和
- */
- void add(char *a, char *b)
- {
- strrev(a);
- strrev(b); //reverse string b
- int la = strlen(a); //cal the length of a
- int lb = strlen(b); //cal the length of b
- int i = 0, j = 0, k = 0, s = 0, inc = 0;
- while(i < la && j < la)
- {
- s = (a[i] & 0XF) + (b[j] & 0XF) + inc;
- a[k++] = (s % 10) + '0'; //add b to a
- inc = s / 10; //store the carry
- i++; j++;
- }
- while(i < la) //length of a is greater than b
- {
- s = (a[i] & 0XF) + inc;
- a[k++] = (s % 10) + '0';
- inc = s / 10;
- i++;
- }
- while(j < lb) //length of b is greater than a
- {
- s = (b[j] & 0XF) + inc;
- a[k++] = (s % 10) + '0';
- inc = s / 10;
- j++;
- }
- if(inc != 0) //at last,if the carry is not 0,store it into a
- a[k++] = inc + '0';
- strrev(a);
- }
2.大数减法
大数减法相对加法较为复杂,但是只要注意借位操作的正确性,还是能够较为轻松写出正确的大数减法运算的。
- //高精度数减法
- string sub(string num1, string num2)
- {
- string ans;
- int *a, *b, i, max, len, len1, len2, k;
- len1 = num1.length();
- len2 = num2.length();
- len = len1;
- max = len;
- a = new int[len];
- b = new int[len];
- for(i = 0; i <= len - 1; i++)
- {
- a[i] = 0;
- b[i] = 0;
- }
- k=0;
- for(i = len1 - 1; i >= 0; i--)
- a[k++] = num1[i] - '0';
- k = 0;
- for(i = len2 - 1; i >= 0; i--)
- b[k++] = num2[i] - '0';
- for(i = 0; i <= len - 1; i++)
- {
- if(a[i] < b[i])
- {
- a[i + 1]--;
- a[i] = a[i] + 10;
- a[i] = a[i] - b[i];
- }
- else
- a[i] = a[i] - b[i];
- }
- while(a[len] == 0 && len > 0 || len >= max)
- len--;
- for(i = len; i >= 0; i--)
- ans.append(1, a[i] + '0');
- return ans;
- }
3.大数乘法
大数乘法利用了大数加法的思想,需要注意的是进位的操作。
- /*
- * 返回两个大数相乘的结果
- */
- string multiple(string a, string b)
- {
- string result = "0", str;
- int i, j, remain, tmp, m, n;
- for(i = a.length() - 1; i >= 0; i--)
- {
- str = "";
- remain = 0; //at first the carry is 0
- for(j = b.length() - 1; j >= 0; j--)
- {
- tmp = (a[i] & 0XF) * (b[j] & 0XF) + remain;
- remain = tmp / 10; //store the carry
- str = (char)(tmp % 10 + '0') + str;
- }
- if(remain != 0)
- {
- str = (char)(remain + '0') + str;
- }
- tmp = 0;
- m = result.length() - (a.length() - i);
- n = str.length() - 1;
- remain = 0;
- while(m >= 0 && n >= 0) //add str to result
- {
- tmp = (result[m] & 0XF) + (str[n] & 0XF) + remain;
- remain = tmp / 10;
- result[m] = (char)(tmp % 10 + '0');
- m--; n--;
- }
- while(m >= 0)
- {
- tmp = (result[m] & 0XF) + remain;
- remain = tmp / 10;
- result[m] = (char)(tmp % 10 + '0');
- m--;
- }
- while(n >= 0)
- {
- tmp = (str[n] & 0XF) + remain;
- remain = tmp / 10;
- result = (char)(tmp % 10 + '0') + result;
- n--;
- }
- if(remain != 0)
- {
- result = (char)(remain + '0') + result;
- }
- }
- return result;
- }