当前位置: 首页 > news >正文

为什么需要高精度运算

基本概念

高精度运算,本质是将大整数按位拆分,用字符串(或数组)保存每一位的数字,完全模拟小学阶段学习的竖式加减乘除规则,逐位计算并处理进位、借位。

  • 存储方式:通常用字符串保存,高位在前、低位在后(和日常书写习惯一致),在计算时会反转字符串,让下标 0 对应最低位,方便对齐处理。
  • 核心操作:进位处理(加法、乘法)、借位处理(减法)、前导零去除、数值大小比较。

三、实现方法

1)加法

运算原理

加法完全模拟小学竖式加法规则:

  1. 将两个数右对齐,从最低位开始逐位相加;
  2. 每一位的和 = 第一个数当前位 + 第二个数当前位 + 低位传来的进位 ;
  3. 当前位结果 = 和 % 10,向高位的进位 = 和 / 10;
  4. 所有位计算完成后,如果还有剩余进位,要在最高位补上。
// 代码中先将字符串反转,是为了让数组下标 0 对应最低位,天然实现右对齐,无需手动补位
string add(string a, string b)
{
if (a.length() < b.length()) swap(a, b); // 大的数字放“上面”,方便操作
reverse(a.begin(), a.end()), reverse(b.begin(), b.end());
string res;
int carry = 0;
for (size_t i = 0; i < a.length(); ++i)
{
int x = a[i] - '0';
int y = i < b.length() ? b[i] - '0' : 0;
int sum = x + y + carry;
res += (sum % 10) + '0';
carry = sum / 10;
}
if (carry) res += carry + '0';
reverse(res.begin(), res.end());
return res;
}

2)减法

运算原理

减法同样模拟小学竖式减法规则:

  1. 先比较两个数的大小,用大数减小数,保证结果非负,最后再补上负号;
  2. 将两个数右对齐,从最低位开始逐位相减;
  3. 如果当前位被减数 < 减数 + 借位,就向高位借 1 当 10,同时标记借位;
  4. 计算完成后,结果会产生多余的前导零,需要去除。
为什么要去除前导零?

减法计算完成后,高位可能会出现连续的 0。例如计算 ,按位计算后反转得到的中间结果会是 ,前面的三个 0 就是前导零。前导零不符合数字的书写规范,也会影响后续运算的长度判断,因此必须去除多余的前导零,仅保留最后一个有效数字(注意结果为 0 时保留一个 0)。

string sub(string a, string b)
{
bool swaped = false;
if (a.length() < b.length() || (a.length() == b.length() && a < b))
{
swap(a, b);
swaped = true;
}
reverse(a.begin(), a.end()), reverse(b.begin(), b.end());
string res;
int carry = 0;
for (size_t i = 0; i < a.length(); ++i)
{
int x = a[i] - '0';
int y = i < b.length() ? b[i] - '0' : 0;
int sum = x - y - carry;
if (sum < 0)
{
sum += 10;
carry++;
} else carry = 0;
res += sum + '0';
}
/*-----去除前导零-----*/
while (res.length() > 1 && res.back() == '0') res.pop_back();
if (swaped) res += '-';
reverse(res.begin(), res.end());
return res;
}

3)乘法

运算原理

乘法模拟小学竖式乘法的错位相加规则:

  1. 第一个数的第 i 位,乘以第二个数的第 j 位,结果会落在结果的第 i+j 位上(最低位从 0 开始计数);
  2. 先把所有位的乘积累加到位对应的位置,暂不处理进位;
  3. 全部相乘完成后,统一从低位到高位处理进位,每一位满十进一;
  4. 最后去除高位多余的前导零,再转换为字符串。

注意:两个长度分别为 La 和 Lb 的数相乘,结果长度最多为 La+Lb 位。

string mul(string a, string b)
{
int La = a.size(), Lb = b.size();
vector<int> res(La + Lb, 0);
reverse(a.begin(),a.end()), reverse(b.begin(),b.end());
for (size_t i = 0; i < a.length(); i++)
{
int x = a[i] - '0';
for (size_t j = 0; j < b.length(); j++)
{
int y = b[j] - '0';
res[i+j] += x * y; // 把每次每位的相乘结果放在数组中,先不进位
}
}
/*-----进位-----*/
for (int i = 0; i < (int)res.size(); i++)
if (res[i] >= 10)
{
res[i+1] += res[i] / 10;
res[i] %= 10;
}
/*-----去除前导零-----*/
while (res.size() > 1 && res.back() == 0) res.pop_back();
string ret;
for (int i = res.size()-1; i >= 0; i--) ret += res[i] + '0';
return ret;
}

4)除法

运算原理

这里实现的是高精度整数除以普通 int 整数(高精度除以高精度复杂度更高,日常场景中高精度除低精度最常用),同样模拟竖式除法规则:

  1. 从被除数的最高位开始,逐位向下计算;
  2. 当前位数值 = 上一位的余数 × 10 + 当前位数字;
  3. 当前位的商 = 当前位数值 ÷ 除数,新的余数 = 当前位数值 % 除数;
  4. 逐位计算完成后,去除商的前导零,同时可以返回余数。

代码中提供了两种写法:一种返回商和余数的 pair,一种只返回商,核心逻辑完全一致。

// 高精度除法:a / b,a为大整数(字符串),b为int,返回商和余数
pair<string, int> div(string a, int b)
{
string res;
int remainder = 0; // 余数
for (size_t i = 0; i < a.length(); ++i)
{
remainder = remainder * 10 + (a[i] - '0');
res += (remainder / b) + '0';
remainder %= b;
}
// 去除前导零
size_t pos = res.find_first_not_of('0');
if (pos == string::npos) res = "0";
else res = res.substr(pos);
return {res, remainder};
}
string divide(string a, int b)
{
if (b == 0) return "Error: Division by zero";
vector<int> num;
for (char c : a) num.push_back(c - '0');
vector<int> result;
int remainder = 0;
for (size_t i = 0; i < num.size(); i++)
{
int current = remainder * 10 + num[i];
result.push_back(current / b);
remainder = current % b;
}
// 去除前导零
size_t start = 0;
while (start < result.size() && result[start] == 0) start++;
if (start == result.size()) return "0"; // 等于0时保留一个0
string ret = "";
for (size_t i = start; i < result.size(); i++) ret += result[i] + '0';
return ret;
}

四、总结

http://www.jsqmd.com/news/1091790/

相关文章:

  • 微信小程序对接minio下载文件签名报错解决
  • 【限时决策框架】:用3分钟完成你的ChatGPT付费评估——含自测清单+成本分摊计算器(仅开放72小时)
  • DeepEval:专业级LLM评估框架的5个核心实战特性解析
  • QQ音乐解析终极指南:打破VIP限制,高效获取高品质音乐资源
  • 为什么越来越多大学生选择学习软件测试?零基础进入IT行业还有机会吗?
  • 石排附近日咖夜酒的咖啡厅
  • 仿真许可证闲置识别怎么做:CAE 团队为什么要区分登录占用和实际计算占用
  • 全新强化学习框架 BeautyGRPO:重塑真实人像
  • 嵌入向量给用户问题做意图分类路由实操
  • 减肥别再啃水煮菜了!这份中医家常食谱,掉秤还不伤脾胃
  • 当C盘亮起红灯时,你的电脑在告诉你什么?
  • B3930 [GESP202312 五级] 烹饪问题
  • 在单台电脑上实现多人分屏游戏的完整指南:NucleusCoop实战教程
  • 存储引擎内核剖析:B+Tree 与 LSM-Tree 的性能博弈,以及如何做可信的 Benchmark
  • 2026年超好用的钢格栅机构,究竟有何独特之处?
  • 读懂2026年CSP-J 初赛:题型分析、命题规律、备考路线
  • 【STL】iostream 编程:流的定义
  • 这个项目是做什么的
  • Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!
  • 如何在Mac上免费永久备份微信聊天记录:WeChatExporter完整教程
  • [MAF预定义ChatClient中间件-01]LoggingChatClient——在调用LLM前后输出日志
  • 深度解析:ToB销售学AI,最该补的是客户研究和方案表达能力
  • 企业实物资产管理:分类、核心要点与规范管控方案
  • 通用PLM根本撑不住!汽车/芯片/新能源研发的痛,它懂[特殊字符]全星研发项目管理APQP软件系统来救场
  • FDE课程: Codex+AI 编程+ SeedanceAI 视频+ AgentAI 智能体
  • 汉明码编码译码推演与验证(P124302158李晨雨)
  • 评估模块(EVM)使用指南:规避法律风险与安全合规要点
  • BUUCTF [第五空间2019 决赛]PWN5:从格式化字符串到任意地址写的实战通关
  • 深度解析TI PCM/DSD179x评估板:从电源隔离到模拟输出的高性能音频DAC设计实战
  • FanControl终极指南:三步搞定Windows风扇智能控制