我正在实现一种算法来为编程类获取一定数量的阶乘。
fn factorial(number: u64) -> u64 {
if number < 2 {
1
} else {
number * factorial(number - 1)
}
}
当我尝试使用100或甚至25时,我收到此错误"thread 'main' panicked at 'attempt to multiply with overflow'"
,所以我尝试换行,结果函数是:
fn factorial(number: u64) -> u64 {
if number < 2 {
1
} else {
number.wrapping_mul(factorial(number - 1))
}
}
这种方式没有恐慌,但结果始终为零,所以我尝试使用f64,结果是
100! = 9332621544394410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
而不是
100! = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
是否有另一种存储结果的方法,以便返回正确的值?
答案 0 :(得分:10)
100!是真正的大号。事实上,适合u64
的最大因子只有20!对于不适合u64
的数字,num::bigint::BigUint
是适当的存储选项。
以下代码计算100!的值。您可以在浏览器here中运行它。
extern crate num;
use num::BigUint;
fn factorial(number: BigUint) -> BigUint {
let big_1 = 1u32.into();
let big_2 = 2u32.into();
if number < big_2 {
big_1
} else {
let prev_factorial = factorial(number.clone() - big_1);
number * prev_factorial
}
}
fn main() {
let number = 100u32.into();
println!("{}", factorial(number));
}
要了解u64
无效的原因,您可以在结果上调用bits
方法。如果你这样做,你会发现价值100!需要 525 位才能存储。这超过8 u64
的存储空间。
答案 1 :(得分:0)
我想通过使用Iterator::fold
的迭代解决方案来补充@Jason Watkins的答案:
extern crate num;
use num::{bigint::BigUint, One};
fn factorial(value: u32) -> BigUint {
(2..=value).fold(BigUint::one(), |res, n| res * n)
}
fn main() {
let result = factorial(10);
assert_eq!(result, 3628800u32.into());
}