什么是高精度运算
高精度运算用于处理超出标准整数类型范围的数值。C++中的 int 和 long long 类型分别能处理的最大值为 2 31 − 1 2^{31}-1 2 3 1 − 1 和2 63 − 1 2^{63}-1 2 6 3 − 1 ,但对于更大的数值,就需要使用高精度运算。
高精度运算的核心思想是将大数分解为多个较小的数字(通常用字符串或数组存储),然后逐位进行运算。
高精度加法
原理
-将两个大数从最低位到最高位逐位相加。
-如果某一位相加的结果大于等于10,则向高位进位。
-最终结果可能比原数多一位。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 string highPrecisionAdd(const string& a, const string& b) { string result; int carry = 0; // 进位 int i = a.size() - 1, j = b.size() - 1; // 从后向前逐位相加 while (i >= 0 || j >= 0 || carry > 0) { int num1 = (i >= 0) ? a[i] - '0' : 0; // 当前位的数字 int num2 = (j >= 0) ? b[j] - '0' : 0; int sum = num1 + num2 + carry; // 当前位的和 result.push_back((sum % 10) + '0'); // 将结果存储为字符 carry = sum / 10; // 更新进位 i--; // 向前移动 j--; } // 因为结果是反向存储的,需要反转 reverse(result.begin(), result.end()); return result; }
高精度减法
原理
确保被减数大于或等于减数,否则结果为负数。
从最低位到最高位逐位相减。
如果某一位不够减,则从高位借1(即加10)。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 string highPrecisionSubtract(const string& a, const string& b) { if (a.size() < b.size() || (a.size() == b.size() && a < b)) { string result = highPrecisionSubtract(b, a); return "-" + result; // 添加负号 } string result; int carry = 0; // 借位 int i = a.size() - 1, j = b.size() - 1; // 从后向前逐位相减 while (i >= 0 || j >= 0) { int num1 = i >= 0 ? a[i] - '0' : 0; // 当前位的数字 int num2 = j >= 0 ? b[j] - '0' : 0; int diff = num1 - carry - num2; // 当前位的差值 if (diff < 0) { diff += 10; // 借位 carry = 1; // 设置借位 } else { carry = 0; // 清除借位 } result.push_back(diff + '0'); // 将结果存储为字符 i--; // 向前移动 j--; } // 去掉前导0 while (result.size() > 1 && result.back() == '0') { result.pop_back(); } // 因为结果是反向存储的,需要反转 reverse(result.begin(), result.end()); return result; }
高精度乘法
原理
将两个大数从最低位到最高位逐位相乘。
每次相乘的结果需要加上之前的结果,并注意进位。
最终结果可能比原数多几位。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 string highPrecisionMultiply(const string& a, const string& b) { int lenA = a.size(), lenB = b.size(); vector<int> result(lenA + lenB, 0); // 结果数组 // 从后向前逐位相乘 for (int i = lenA - 1; i >= 0; i--) { for (int j = lenB - 1; j >= 0; j--) { int mul = (a[i] - '0') * (b[j] - '0'); int sum = mul + result[i + j + 1]; result[i + j] += sum / 10; // 进位 result[i + j + 1] = sum % 10; // 当前位 } } // 转换为字符串 string res; for (int num : result) { if (res.empty() && num == 0) continue; // 去掉前导0 res.push_back(num + '0'); } return res.empty() ? "0" : res; }
高精度除法
原理
高精度除法较为复杂,通常需要模拟手工除法的过程。
从高位到低位逐位试除,记录商和余数。
余数用于下一次的试除。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 pair<string, string> highPrecisionDivide(const string& a, const string& b) { string quotient, remainder; int lenA = a.size(), lenB = b.size(); // 逐位试除 for (int i = 0; i < lenA; i++) { remainder += a[i]; // 添加一位到余数 int temp = 0; // 用于存储当前的商 // 试除 while (remainder >= b) { remainder = highPrecisionSubtract(remainder, b); // 减去除数 temp++; } quotient += to_string(temp); // 添加商的当前位 } // 去掉前导0 quotient.erase(0, quotient.find_first_not_of('0')); remainder.erase(0, remainder.find_first_not_of('0')); return {quotient, remainder}; }