大家好!
大概 4 年前,我在 URLO 上首次发布了 dashu,之后也一直在英文社区里和大家交流迭代——不过在中文社区这边,还一直没有专门做过宣传。所以今天想正式跟中文 Rust 社区的朋友们介绍一下 dashu 的现状!
关于这个名字——dashu 就是"大数"的拼音。没错,它是一个由中文命名的 Rust 库。项目 logo 是一棵榕树,取的是"大树"与"大数"的谐音双关:用一棵参天大树的形象来隐喻"大数"这个主题。🌳
Dashu 是一套纯 Rust 编写的任意精度数字库,完全支持 no_std。从第一天起,我们的目标就是打造一个 Rust 原生的、对标经典 C 技术栈 GNU GMP + MPFR + MPC 的替代方案——但你不需要安装 C 工具链,没有 unsafe FFI,也不会有一堆构建问题。
它由一组子 crate 组成,统一通过元 crate dashu 重新导出:
| 类型 | dashu 别名 | 替代 |
|---|---|---|
UBig / IBig |
Natural / Integer |
GMP (mpz) |
FBig / DBig |
Real / Decimal |
MPFR (mpfr) |
RBig |
Rational |
GMP (mpq) |
CBig |
Complex |
MPC (mpc) |
随着最近 dashu-cmplx(任意精度复数,CBig)的加入,最后一块拼图已经就位:dashu 现在覆盖了整数、有理数、实数浮点(二进制 和 十进制)以及复数——在浮点和复数方面实现了正确舍入的超越函数,以及 C99 Annex G 的分支切割/有符号零语义。至此,GMP+MPFR+MPC 的功能边界已全部补齐。
下面是一些令人兴奋的新进展,以及为什么我认为现在是尝试 dashu 的最佳时机。
1. 功能已基本完备——v1.0 将于年底发布
当前版本是 0.5.0,功能上已经基本完备。接下来的计划:
- v0.5.x 小版本主要进行正确性改进和非破坏性的性能优化(例如:保证正确舍入的 Ziv 重试循环、有符号零的边界情况、更快的底层 kernel)。全部是增量改进,不会引入破坏性变更。
- v1.0 预计在今年年底发布,主要工作将是定稿和稳定公开 API。
如果你想了解详细计划(以及哪些功能推迟到 v1.0 之后),这里有公开路线图:
除了功能的完善,这个开发周期还带来了大量性能优化——更好的除法和乘法 kernel、Montgomery 归约器、所有权感知的算术运算,以及带缓存的超越函数包装器(CachedFBig / CachedCBig,暴露为 FastReal / FastComplex),它们共享一个常量缓存,使得反复进行高精度超越函数调用时,π 等常量不必每次都从头计算。
关于性能,有两个独立的第三方基准测试可以参考:
坦白说,dashu 目前还不是最快的任意精度库——Rust 生态里已有 rug(GMP 的 Rust 绑定)等基于成熟 C 库的方案。但 dashu 的表现已经相当不错了,尤其在整数运算方面,效率远高于 num-bigint,并且作为纯 Rust 实现,没有 C 依赖带来的构建负担,在大多数场景下提供了很有竞争力的性能。
2. 有了正式的在线用户手册
API 文档适合查阅,但它们不一定能告诉你如何使用这个库。因此 dashu 现在有了一本完整的 mdBook 用户手册,包含简洁的概述和可运行的示例,涵盖类型、构造、转换、解析/打印、序列化、所有运算(算术、指数/对数、三角/双曲、位操作、数论),以及 FAQ、性能说明、速查表和标准合规性页面:
它是 docs.rs 上的 API 文档 的补充资料,也是了解 dashu 能力的最快途径。(顺便一提,一个小而有趣的里程碑:dashu 终于有了自己的 logo/图标,来搭配这个逐渐成熟的代码库。)
3. 现在可以直接从 Python 体验 dashu——无需 Rust 工具链
新增了基于 PyO3 的 Python 绑定,让你无需搭建 Rust 项目就能上手体验。它将 dashu 的任意精度整数、有理数、浮点数和复数暴露给 Python:
pip install dashu-rs
它是一个友好的核心功能试验场(说真的,就其本身而言,也是一个不错的 Python 生态独立任意精度包)。如果你一直好奇但不想仅仅为了尝试就创建一个 Cargo 项目,这就是为你准备的。
⚠️ 目前有一个限制:绑定还处于早期阶段,PyPI 上目前只有 针对 Python 3.12 + Linux x86_64 的单个 wheel。更多平台和版本将陆续推出——但如果你正好是这个环境,现在就可以 pip install 直接开用。
4. 请试试看——在 API 冻结之前,我非常想听到你的反馈
这是最重要的请求。v1.0 将锁定公开 API,所以现在是影响 API 设计的理想窗口。如果有任何让你觉得别扭的 API 设计,如果有缺失的类型或 trait,如果文档不够清晰,或者如果你遇到了 bug——请一定告诉我。
我会非常乐意并在 v1.0 API 冻结之前积极修复问题。Bug 报告、API 人体工学反馈、缺失功能请求、与 GMP/MPFR/MPC 的对比基准测试——所有这些都非常受欢迎,而且在当下尤其有帮助。
- 仓库 & Issues:https://github.com/cmpute/dashu
- Crate:https://crates.io/crates/dashu
- API 文档:https://docs.rs/dashu
- 用户手册:英文 | 中文
- Python 绑定:https://pypi.org/project/dashu-rs/
[dependencies]
dashu = "0.5"
感谢阅读——也提前感谢每一位愿意试用 dashu 的朋友。在 v1.0 发布前的最后几个月里,你的反馈将直接让 1.0 版本变得更好。🙏
附:一些有趣的代码速览
以下是一些能让你快速感受 dashu 能力的示例——都是一行 cargo add dashu 就能跑的真实代码。
🚀 编译时常量大数
use dashu::{ubig, cbig, static_cbig, Base32};
// 任意进制的编译时常量
const E: UBig = ubig!(314159265358979323846264338327950288419716939937);
const H: UBig = ubig!(deadbeef base 16);
// 十进制浮点常量,指数可达 10^100000
const BIG_NEG: DBig = dbig!(-1e100000);
// 复数常量,支持代数形式和坐标对形式
const Z1: CBig = cbig!(11 + 100i); // 3 + 4i(二进制系数自动解析)
const Z2: CBig = cbig!(0, 1); // 纯虚数 i
// 任意大小的静态大数(需要 Rust ≥ 1.64)
static HUGE: &CBig = static_cbig!(
0xffffffffffffffffffffffffffffffffffffffffffffffff,
0xffffffffffffffffffffffffffffffffffffffffffffffff
);
🔢 Mersenne 素数上的费马小定理验证
use dashu::{ubig, integer::MontgomeryRepr};
// M607 —— 一个 183 位的 Mersenne 素数
let p = ubig!(2).pow(607) - ubig!(1);
let ring = MontgomeryRepr::new(p.clone());
// 一行代码验证 a^(p-1) ≡ 1 (mod p)
let a = ring.reduce(ubig!(123));
assert_eq!(a.pow(&(p - ubig!(1))), ring.reduce(ubig!(1)));
🎯 正确舍入的累加求和
use dashu::{dbig, Decimal};
let vals = [dbig!(1), dbig!(1e-70), dbig!(-1)];
// fold 丢失了 1e-70 —— 被舍入了
let folded = vals.iter().cloned().fold(Decimal::ZERO, |a, b| a + b);
assert_eq!(folded, dbig!(0)); // 丢失精度!
// Sum 是正确舍入的 —— 像 MPFR 的 mpfr_sum 一样精确
let summed: Decimal = vals.iter().sum();
assert_eq!(summed, dbig!(1e-70)); // 精度不丢!
你可以在一次累加中求任意数量值的和,dashu 保证不会因为中间舍入丢失有效数字——这在数值积分和 Kahan 求和等场景中至关重要。
π 计算——带缓存,只算一次
use dashu::float::{ConstCache, round::HalfAway};
let mut cache = ConstCache::new();
let pi_100 = cache.pi::<10, HalfAway>(100).value(); // 从头计算 100 位
let pi_1000 = cache.pi::<10, HalfAway>(1000).value(); // 扩展到 1000 位,复用状态!
assert!(pi_1000.to_string().starts_with("3.141592653589793"));
第二次调用只需支付从 100 到 1000 位的增量计算成本——底层使用二进制分裂法,状态在两次调用间保留。
📐 从浮点数精准恢复有理数
use dashu::Rational;
// simplest_from_f32 找到能舍入回原浮点值的"最简"有理数
let d = Rational::simplest_from_f32(22. / 7.).unwrap();
assert_eq!(d.to_string(), "22/7"); // 完美往返!
这对于从浮点常量的近似值中恢复精确的有理数表达非常有用。
🔮 复数运算——Mandelbrot 粒子
以下是一个简化版的 Mandelbrot 迭代核心。当原生 f64 在缩放深度 ~3e-16 时就变成均匀色块时,dashu 可以保持每个像素的细节,想放多大就放多大:
use dashu::{cbig, Complex};
let c = cbig!(-0.7269 + 0.1889i);
let mut z = Complex::ZERO;
let max_iter = 1000;
for _ in 0..max_iter {
z = &z * &z + &c; // z = z² + c —— 任意精度!
if z.sqr_norm() > 4.into() {
break; // 逃逸了
}
}
// z 的精度完全由你决定 —— 上下文精度设多少就是多少
dashu 的复数类型完整支持 C99 Annex G 的分支切割和有符号零语义,复数的 sqrt、ln、asin、acosh 等超越函数全部正确舍入。
⚡ 所有权感知的算术运算——零分配
dashu 的算术运算针对所有权做了深度优化。当一个操作数是 owned 值时,运算结果可以复用它的内存:
use dashu::{ubig, Natural};
let a = Natural::from(10u32).pow(10_000); // 一个大数
let b = Natural::from(20u32).pow(10_000); // 另一个大数
let c = a * b; // 如果 a 足够大,直接在其内存上就地运算
这种优化意味着在高精度运算链中,内存分配次数远少于传统的"每个中间结果都是新分配"的模式。
🔧 模块化算术——自带格式化
use dashu::{ubig, integer::ConstDivisor};
let ring = ConstDivisor::new(ubig!(10000));
let x = ring.reduce(ubig!(12345));
let y = ring.reduce(ubig!(55443));
assert_eq!(format!("{}", x - y), "6902 (mod 10000)");
dashu 已经为严肃的科学计算、密码学、数值分析、计算机代数系统等场景做好了准备——而这一切都在 cargo add dashu 一步之内。欢迎大家试用、提 issue、贡献代码!
Ext Link: https://zyxin.xyz/dashu-zh/
评论区
写评论还没有评论