How do I calculate a multiple factorial using num_bigint in Rust?
I am trying to calculate a factorial of a factorial in Rust using the NumBigInt library. I've gotten to the point where I can calculate a factorial:
use num_bigint::BigUint;
use num_traits::{One, Zero, FromPrimitive};
fn factorial(n: usize) > BigUint {
let mut f: BigUint = One::one();
for i in 1..(n+1) {
let bu: BigUint = FromPrimitive::from_usize(i).unwrap();
f = f * bu;
}
f
}
pub fn main() {
println!("Starting calculation...");
println!("{}", factorial(5));
}
I want to do a double factorial, like:
pub fn main() {
println!("Starting calculation...");
println!("{}", factorial(factorial(5)));
}
However, this throws the following error because the data types are different:
error[E0308]: mismatched types
> src/main.rs:16:30

16  println!("{}", factorial(factorial(5)));
 ^^^^^^^^^^^^ expected `usize`, found struct `BigUint`
How can I repeat this function using BigUint
instead of usize
?
1 answer

The problem is that you first want to use a
usize
and then aBigUint
as your function parameter, while your parameter is set to be ausize
.To fix this you should make your
factorial
function generic and then only allow those types that make sense for your particular method.I took your example and extended it to allow for all unsigned integer types:
use num_bigint::BigUint; use num_traits::{One, FromPrimitive, Unsigned}; use num::{Integer, NumCast, ToPrimitive}; fn factorial<N: Unsigned + Integer + ToPrimitive>(n: N) > BigUint { let mut f: BigUint = One::one(); let end: usize = NumCast::from(n).unwrap(); for i in 1..(end + 1) { let bu: BigUint = FromPrimitive::from_usize(i).unwrap(); f = f * bu; } f } pub fn main() { println!("Starting calculation..."); println!("{}", factorial(factorial(5 as u32))); }
This will however lead to not allowing
factorial(5)
, because5
is treated as ani32
by default, which can be signed. If you wish to allow for signed types and instead fail at runtime you can do something like that:use num_bigint::BigUint; use num_traits::{One, FromPrimitive}; use num::{Integer, NumCast, ToPrimitive}; fn factorial<N: Integer + ToPrimitive>(n: N) > BigUint { let mut f: BigUint = One::one(); let end: usize = NumCast::from(n).expect("Number too big or negative number used."); for i in 1..(end + 1) { let bu: BigUint = FromPrimitive::from_usize(i).unwrap(); f = f * bu; } f } pub fn main() { println!("Starting calculation..."); println!("{}", factorial(factorial(5))); }