关于高精度和链表的详细讲解(从属于GESP五级)

本章内容

高精度
链表

 

位数再多,只管稳稳进位,终会把答案写满。

一、高精度

1. 什么是高精度

  • 定义

“高精度整数”指不受 C++ 原生整型 (int / long long) 位宽限制,而用数组模拟任意位数的大整数。

  • 必要性

64 位 long long 仅能保存到 9 × 10¹⁸。五级真题里随手就超出:

    • • 2023-12 单选 11 要填写“高精度加法”代码行,默认操作数可达上百位;
    • • 2025-03 单选 15 要补全“高精度乘法”进位处理,测试数据位长同样远超原生类型;
    • • 2024-09 单选 14 直接考察高精度四则运算复杂度与实现要点。
    • • 在组合数、阶乘、超长斐波那契 等场景里也必须使用高精度。

2. 数据结构设计

2.1 存储方案

① 先谈“存储哲学”——把大整数拆成“块”并线性摆放

高精度实质上是把人类熟悉的十进制笔算过程,翻译成 C++ 的数组操作。任何一个千位、万位甚至百万位的十进制整数,都可以视作“若干个低位到高位连续排列的数字块”。高精度使用者的责任,就是决定“每个块存多少信息”、决定“块们的排列方向”,并确保 进位、借位、比较、截零 等操作在这样的布局下都能高效完成。存储方案因此成为高精度体系的基石:如果选得好,后续加减乘除皆可顺滑;若选得拙劣,则会在常数时间和代码复杂度上付出高昂代价。

② “一位一存”——最朴素但也最易懂的方案

最原始的做法是:把十进制的每一位(0‥9)直接存在 int 数组里。假设要存 31415926,则定义 int a[8],把低位 6 放到 a[0](也可以存在 a[1]),再依次存 2、9、5 … 直至最高位 3 存入 a[7]。这种“小端倒序”布局有几大显见好处:

  • • 程序逻辑几乎与手算一一对应:加减从 a[0] 开始循环,满 10 进 1,直观不易错。
  • • 输出时只需逆序打印即可;调试时直接扫数组就能看到各位数字。
  • • 在五级最常见的“补全代码”单选题中,命题人为了降低阅读门槛,也常给出这种一位一存模板,让考生专注在“进位语句”或“前导零删除”细节。

然而,“一位一存”也有天然瓶颈:循环次数与十进制位数完全等长。5000 位整数相加就得跑 5000 次循环,乘法则是平方级——两数都是 5000 位时,朴素乘法将运行 25 000 00 次乘-加-进位,极容易被 OJ 的 1 s 时限卡住。再者,同样 5000 位数字,数组占 5000×4 B≈20 KB,乘法的中间数组更大,对高速缓存不友好。

在实际使用者中,若题目已声明“输入位数 ≤ 2000”且只牵涉加法或减法,使用一位一存完全能 AC;若涉及乘法、尤其是阶乘、快速幂等 量级循环,则需要考虑更高效的“块存储”。

③ 升级一步:十进制“块”存储,为什么是 10⁴ 或 10⁹?

所谓块存储,就是把若干位十进制数字打包进一个元素。32 位平台常用 BASE=10 000(4 位),因为 9999×9999 不会溢出 32 位有符号整型。64 位平台可提到 BASE=1 000 000 000(9 位);999 999 999×999 999 999≈10¹⁸ 仍落在 64 位无符号范围,但若要存进位之和就需要 long long 或加上额外 carry。对比单独一位,这样做的优势肉眼可见:

  • 位数压缩:原本 5000 位 → ceil(5000/9)=556 块;循环立减 9 倍。
  • Cache 友好:数据更紧凑,CPU 每次读入一次 cache line 可以操作更多“有效位”,缓存命中率提升。
  • 乘法加速:乘法内部两层循环加进位处理常数大幅下降,BASE=10⁹ 的朴素乘法可轻松处理一万位 × 一万位于 0.5 s 内,而单位存储会超时。

但块也不是越大越好。BASE=10¹⁰ 会让一次相乘结果溢出 64 位,需要手写 128 位拆分或使用 __int128。竞赛常用 10⁹ 正是折中的“黄金”——既压缩了位数,又能在支持 __int128 的 GNU C++14 下安全地乘完后取低 64 位和进位 64 位。本篇后续给出的数组模板也选用 BASE=10⁹

④ “大端”还是“小端”?倒序到底好在何处?

  • 小端 (Little-Endian) 命名来源于计算机字节序,在高精数组中意味着“低位在下标 0 or 1”。优点:从低到高自然遍历,符合加减乘除的进位传播方向;缺点:打印要倒序。
  • 大端 (Big-Endian) 则高位在 0,下标越大位权越小,打印方便,但每次运算都要从末尾往前走,写法繁琐。

我们常见和常做的,就是以小端基础,倒序适应我们的四则运算。

2.2 统一符号

① 把正负逻辑从核心运算里剥离
加、减、乘、除的本质都发生在“非负绝对值”之间。如果每一步都掺杂正负判断,会让代码分支膨胀、进位逻辑混乱。

② 避免“负零”
若 0 仍保留 s = -1,那么两个“零”比较会出现“‐0 < +0”的假象。统一约定:只要值为 0,就把符号改回 +1

③ 简化比较
先看符号即可粗判大小(正数必然大于负数),只有符号相同才需

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值