
num-bigint LibraryWhen working with integers in Rust, we usually use primitive types like i32, i64, or u64. However, these types have limitations when it comes to representing very large integers, as they can only store fixed-size values. If you need to work with arbitrarily large integers, the num-bigint library comes in handy. In this article, we’ll explore how to use num-bigint to perform various operations on large integers.
First, let’s add the num-bigint and num-traits crates to our project. Add the following dependencies to your Cargo.toml file:
[dependencies]
num-bigint = "0.4.4"
num-traits = "0.2.18"
Now, you can use the BigInt and BigUint types in your Rust code, as well as various traits provided by num-traits.
BigInt represents a signed arbitrary precision integer, while BigUint represents an unsigned arbitrary precision integer. To create and initialize these types, we can use the following methods:
use num_bigint::{BigInt, BigUint};
use num_traits::FromPrimitive;
fn main() {
let a: BigInt = 100.into();
let b: BigInt = BigInt::from(200);
let c: BigInt = BigInt::from_i64(300).unwrap();
let d: BigUint = 1000.into();
let e: BigUint = BigUint::from(2000);
let f: BigUint = BigUint::from_u64(3000).unwrap();
}
Here, we’re using the From trait to convert primitive integers to BigInt and BigUint values. The FromPrimitive trait provides methods for converting primitive types to BigInt and BigUint and returns an Option that needs to be unwrapped.
num-bigint supports various arithmetic operations like addition, subtraction, multiplication, and division. Here’s an example of how you can perform these operations:
use num_bigint::BigInt;
use num_traits::Zero;
fn main() {
let a: BigInt = "12345678901234567890".parse().unwrap();
let b: BigInt = "98765432109876543210".parse().unwrap();
let sum = &a + &b; // Use references for arithmetic operations
let difference = &b - &a;
let product = &a * &b;
// Ensure b is not zero before dividing
let quotient = if !b.is_zero() {
Some(&a / &b)
} else {
None
};
println!("Sum: {}", sum);
println!("Difference: {}", difference);
println!("Product: {}", product);
println!("Quotient: {:?}", quotient);
}
You can compare BigInt and BigUint values using standard comparison operators, such as <, >, ==, !=, <=, and >=. For example:
use num_bigint::{BigInt, BigUint};
fn main() {
let a: BigInt = 100.into();
let b: BigInt = 200.into();
if a < b {
println!("a is less than b");
} else if a > b {
println!("a is greater than b");
} else {
println!("a is equal to b");
}
}
num-bigint also provides methods for other mathematical operations, such as modulo, exponentiation, and greatest common divisor (GCD).
use num_bigint::{BigInt, BigUint};
use num_traits::One;
use num_integer::Integer;
fn main() {
let a: BigInt = BigInt::from(12345); // Explicitly creating BigInt from integer
let b: BigInt = BigInt::from(67890); // Explicitly creating BigInt from integer
let modulo = &a % &b; // No changes needed here
let gcd = a.gcd(&b); // No changes needed here
let exp = BigUint::one() << 100; // This calculates 2^100 correctly
println!("Modulo: {}", modulo);
println!("GCD: {}", gcd);
println!("2^100: {}", exp);
}
In this example, we’re using the % operator to calculate the modulo, the gcd method to find the greatest common divisor, and bit-shifting to calculate 2 raised to the power of 100.
The num-bigint library provides an easy-to-use and efficient way to work with arbitrarily large integers in Rust. With support for a wide range of operations, from basic arithmetic to advanced mathematical functions, it’s an invaluable tool for any Rust developer who needs to handle large numbers.