不能直接用int64或float64处理超长字符串大整数,因为int64位宽固定、易溢出,float64会丢失精度;必须模拟竖式加法:双指针从末尾逐位相加、处理进位、最后反转结果。

为什么不能直接用 int64 或 float64 处理超长字符串大整数
因为 Go 原生整型有固定位宽,int64 最大只能表示约 9×10¹⁸,一旦字符串长度超过 20 位(比如 "1234567890123456789012345"),转成 int64 必然溢出或 panic;float64 更不可靠——它会丢失低位精度,比如 "9999999999999999999999999" + "1" 可能算成 "10000000000000000000000000"(看起来对),但换成 "9999999999999999999999998" + "1" 就可能错成 "9999999999999999999999999"(实际应为 "9999999999999999999999999"?等等,别信 float,它连这个都保不准)。所以必须按字符串逐位模拟手算加法。
手动实现字符串大整数加法的核心逻辑
本质是「从右往左逐位相加 + 进位」,和小学竖式完全一致。关键点不在“能不能写”,而在“怎么写才健壮”:
- 两个字符串可能长度不同,需对齐末尾(不是左对齐),建议用双指针从末尾开始扫描
- 进位变量
carry初始为 0,每轮计算:digit1 + digit2 + carry,然后sum % 10是当前位结果,sum / 10是新进位 - 循环结束后,若
carry > 0,必须追加一位(例如"999" + "1"→"1000") - 结果要反转:因为是从低位往高位算,先 append 的是个位,最后得
reverse一下
示例片段(不处理负号,仅正整数):
func addStrings(num1, num2 string) string {
i, j, carry := len(num1)-1, len(num2)-1, 0
res := []byte{}
for i >= 0 || j >= 0 || carry > 0 {
d1 := 0
if i >= 0 {
d1 = int(num1[i] - '0')
i--
}
d2 := 0
if j >= 0 {
d2 = int(num2[j] - '0')
j--
}
sum := d1 + d2 + carry
res = append(res, byte(sum%10)+'0')
carry = sum / 10
}
// 反转字节切片
for i, j := 0, len(res)-1; i <h3>遇到负数怎么办:先判断符号,再分情况调用</h3><p>Go 标准库没有内置大整数符号处理逻辑,<code>math/big</code> 虽然能搞定,但如果你明确想自己写、或项目禁用 <code>big</code>,就得手动处理符号组合:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8096" title="Alibabacloud Sdk Client Initialization For Golang"><img
src="https://img.php.cn/upload/skill/000/000/081/179186233233253.jpg" alt="Alibabacloud Sdk Client Initialization For Golang" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill8096" title="Alibabacloud Sdk Client Initialization For Golang" class="overflowclass">Alibabacloud Sdk Client Initialization For Golang</a>
<p class="overflowclass">初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。</p>
</div>
<a rel="nofollow" href="/xiazai/skill8096" title="Alibabacloud Sdk Client Initialization For Golang" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
-
"+" + "+":直接走上面的加法 -
"-" + "-":提取绝对值,相加后加负号 -
"+" + "-"或"-" + "+":本质是减法,需实现字符串减法(注意借位、前导零、谁更大),比加法复杂得多
更稳妥的做法是——直接用 math/big.Int。它底层就是字符串/数组模拟,且已处理所有边界(负数、前导零、空字符串、超长位数)。只要你的场景允许引入标准库,就别重复造轮子:
import "math/big"
func addBig(a, b string) string {
x := new(big.Int)
y := new(big.Int)
x.SetString(a, 10)
y.SetString(b, 10)
return x.Add(x, y).String()
}
注意:SetString 返回 (*Int, bool),第二个返回值表示是否成功解析,生产环境务必检查 ok。
性能与边界陷阱:别忽略空串、全零、科学计数法输入
真实数据里常混入异常输入,比如 ""、"000"、"+123"、甚至 "1e10"(虽然严格说这不是整数字符串)。手写实现时容易漏判:
- 空字符串:应视为
"0",或直接报错,取决于业务约定 - 全零字符串(如
"0000"):加法结果不该带前导零,需在最终结果做strings.TrimLeft(result, "0"),但注意结果为"0"时不能全删光 - 带符号前缀:
"-123"和"+456"都要提前识别并剥离,否则'+'或'-'会干扰数字解析 - 非数字字符:比如
"12a3",应在解析阶段就拒绝,而不是等到num[i]-'0'出现负值才崩
真正难的不是加法本身,而是把输入归一化、错误分类、输出标准化这一整套流程。很多线上 bug 不是算法错,是 "0" 和 "" 没区分清楚,或者没处理 "-0" 这种边缘情况。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










