num-bigint: dynamic width big integers in pure Rust
Big integer types for Rust
At a glance
- What is it?
- num-bigint is the Rust crate for arbitrary precision integers, offering a signed BigInt and an unsigned BigUint whose width grows with the value. It is pure Rust, works on rustc 1.60 and later, and its own documentation includes a comparison table of the alternatives that admits when a different crate fits better.
- Who is it for?
- num-bigint suits a Rust codebase that needs integers wider than 128 bits without a build dependency on a C library, especially where dynamic width is a feature rather than a compromise, since a value grows to fit what it holds.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 62 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Two types and a width that follows the value
num-bigint provides BigInt and BigUint, a signed and an unsigned arbitrary precision integer, and the distinguishing property is that the width is dynamic. The magnitude of the number is not fixed at compile time, so a value that grows large costs more memory and a value that stays small costs less, which is the behaviour most callers want from a big integer type in application code. The feature the project lists for itself is dynamic width plus number theoretical functions, and those two words cover the range from a value that is simply too big for u128 to the arithmetic that shows up in cryptographic and number theory work.
The crate is pure Rust with no build script pulling in a C library, it is published on crates.io, and the documentation is on docs.rs. The manifest is unremarkable in the way a well maintained crate should be: version 0.5.1, edition 2021, a minimum Rust version of 1.60, and a dependency on num-integer and num-traits, both pinned with the i128 feature enabled so the wide primitive types are available.
Adding it is one entry in your manifest:
[dependencies]
num-bigint = "0.5"The comparison table is the most useful part
The project documentation includes a table of alternatives, and it is worth reading closely because it is unusually candid. The project states that while num-bigint strives for good performance in pure Rust code, other crates may offer better performance with different trade-offs.
Four of the alternatives are also pure Rust and differ mainly in their width model and their toolchain floor. awint is fixed width, can live on the heap or the stack, and offers concatenation macros, needing rustc 1.70. bnum is fixed width and aims for parity with the Rust primitive types including floats, needing 1.87. crypto-bigint is fixed width and stack only, needing 1.85. ibig is dynamic width like num-bigint with number theoretical functions, and needs only 1.49, which is the lowest floor of the group. The last entry is different in kind: rug is licensed LGPL-3.0 or later and bundles GMP through gmp-mpfr-sys, which brings the full feature set of GMP, MPFR and MPC with it. That is the real trade-off in one line: a C library and a copyleft licence against a pure Rust implementation and a permissive one.
The std feature is on by default, and older toolchains care
There is one feature flag that surprises people, which is the std feature. It is enabled by default, and the documentation is explicit that it is mandatory before Rust 1.36 and the stabilized alloc crate. If you depend on num-bigint with default-features turned off, you have to enable the std feature yourself if your compiler is not new enough.
That is a small paragraph in the documentation and a real upgrade hazard. A project that turns off default features across its dependency tree, a common habit for keeping a binary small or for a no_std target, can break on a big integer operation with a compiler older than the cutoff, and the error will point at the crate rather than at the feature flag. The full feature list in the manifest shows the shape of the rest: the std feature, arbitrary and quickcheck for property testing, serde for serialisation, and the random generation features discussed next.
[features]
default = ["std"]
std = ["num-integer/std", "num-traits/std"]
arbitrary = ["dep:arbitrary"]
quickcheck = ["dep:quickcheck"]
rand_0_9 = ["rand_core_0_9", "dep:rand_0_9"]
rand_core_0_9 = ["dep:rand_core_0_9"]
rand_0_10 = ["rand_core_0_10", "dep:rand_0_10"]
rand_core_0_10 = ["dep:rand_core_0_10"]
serde = ["dep:serde"]Random generation and the version matching trap
Generating random big integers is behind a feature rather than being always available, and the way it is wired is the detail that catches people. The crate supports random generation when either the rand_0_9 or the rand_0_10 feature is enabled, and the documentation states plainly that you must use the same version of rand as the feature you enable. The example shows the pair together:
rand = "0.10"
num-bigint = { version = "0.5", features = ["rand_0_10"] }So the feature name is not decorative, it is the version of the rand API the crate is compiled against, and the dependency is renamed to make that explicit in the manifest, where the rand_0_9 and rand_0_10 entries both point at the rand package with different version requirements. If your application already depends on a different rand version, enabling the wrong feature will not compile, and the fix is to match them. There is also a more restricted route: the rand_core_0_9 and rand_core_0_10 features pull in the core traits only, for callers who want the traits without the full generator surface.
The other optional features exist for testing and storage rather than for arithmetic. The arbitrary and quickcheck features support property based testing of code that uses big integers, which is a good sign about how the crate is treated by its users.
Benchmarks sit in the repository
The repository carries a benches directory, and the bench list in the manifest is a good indication of what the crate is used for. There are benchmarks named bigint, factorial, gcd and roots, and the gcd, bigint and roots benchmarks all require the rand_0_10 feature, so they generate their own input. The fourth one, factorial, does not, which makes sense for a benchmark whose input is a fixed number.
The last benchmark is the most interesting: shootout-pidigits, with the harness turned off. That name refers to the Project Euler problem that computes the thousandth decimal digit of a factorial, and disabling the standard harness means it is written as a standalone program that measures its own time rather than as a library benchmark. It is a small decision that says the author wanted to compare this implementation against others on a problem that is famously sensitive to the multiplication and conversion routines, and the result of that comparison is what the alternatives table is about.
Versioning, licensing and where the project stands
The compatibility statement is that num-bigint is tested for rustc 1.60 and greater, which matches the rust-version field in the manifest, and the edition is 2021. Release notes live in a separate RELEASES.md file, and the repository publishes no tagged GitHub releases, so that file is the changelog to read.
The licensing is the dual MIT or Apache-2.0 model, with both licence files in the repository root, and the contribution rules say that unless a contributor states otherwise, any contribution is dual licensed in the same way and with no additional terms. For a crate that sits underneath other people's libraries, that choice is more than a formality, because it lets the code be used in a project under either licence.
The last push was on 2026-08-21, and the crate version is 0.5.1. A major version below 1.0 in a crate this old is a statement about the API's willingness to change, and the good news is that the documentation on docs.rs is built with the full feature set, including the random generation features, the property testing features and serde, so the rendered documentation is the reference for the complete API rather than the default one.
Editorial conclusion
num-bigint suits a Rust codebase that needs integers wider than 128 bits without a build dependency on a C library, especially where dynamic width is a feature rather than a compromise, since a value grows to fit what it holds. It is the wrong choice for a fixed size cryptographic integer, where the table in the project notes points at a fixed width stack only crate, and it is the wrong choice when you want the performance of a mature C library, since the alternative that bundles GMP is licensed differently and brings a native build with it. Before you pick it, read the alternatives table rather than the feature list, because the choice is really about width model, toolchain and licence. If you use the random generation feature, check that the feature flag matches the version of rand in your dependency tree, and remember that the crate carries a minimum rustc of 1.60 and is dual licensed as MIT or Apache-2.0 at your option.
Frequently asked questions
How do I add num-bigint to a Rust project?
Add one entry to your manifest under dependencies, namely num-bigint = "0.5". The crate provides the BigInt and BigUint types and is published on crates.io, with its documentation on docs.rs.
Which Rust version does num-bigint support?
The crate is tested for rustc 1.60 and greater, and the manifest sets the same minimum as its rust-version field with edition 2021. The alternatives listed in the project notes have different floors, from ibig at 1.49 up to bnum at 1.87.
How do I generate random big integers with num-bigint?
Enable the rand_0_9 or the rand_0_10 feature, and you must use the same version of rand as the feature you enable, so rand 0.10 pairs with rand_0_10. The rand_core_0_9 and rand_core_0_10 features are available when you only need the core traits.
What is the difference between num-bigint and rug?
num-bigint is a pure Rust implementation with dynamic width and number theoretical functions, licensed MIT or Apache-2.0. rug is licensed LGPL-3.0 or later and bundles GMP through gmp-mpfr-sys, giving access to the full features of GMP, MPFR and MPC at the cost of a native library.
Can num-bigint be used without the standard library?
The std feature is enabled by default and is mandatory before Rust 1.36 and the stabilized alloc crate. If you depend on the crate with default-features turned off, you have to enable the std feature yourself when your compiler is not new enough.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rust-num-num-bigint)Was this useful?