计算阶乘时无法存储大值

时间:2018-03-19 02:52:39

标签: rust

我正在实现一种算法来为编程类获取一定数量的阶乘。

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

是否有另一种存储结果的方法,以便返回正确的值?

2 个答案:

答案 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());
}