繁体   English   中英

简单的C ++阶乘程序

[英]Simple C++ factorial program

作为家庭作业,我需要一个读取非负整数的程序,并计算并打印其阶乘。 到目前为止我编写了代码,但如果我尝试输入50! 结果为0.它适用于较小的数字。 任何帮助将非常感激。

#include <iostream>

using namespace std;

int main()
{
    int counter = 1;
    int number;

    cout << "Please enter a number: ";
    cin >> number;

    int factorial = number;
    while (counter != number)
    {
        factorial = factorial * (number - counter);
        counter++;

    }

    cout << "The factorial of " << number << "! is: " << factorial << endl;
    return 0;
}

50! 30414093201713378043612608166064768844377641568960512000000000000 ,对于一个int来说太大了。 由于整数溢出,结果为0。

如果要计算大因子,则需要使用一些BigInteger类。 看看这个: 线程

已经有了一些答案。 然而,他们都缺乏提供一些(imho)重要事实:

无论您选择多大的结果类型,您的程序将能够计算的内容总是有限制的。

在正常的口袋计算器69! 是他们可以显示的最大因子(因为它是具有两位数指数的最大因子)。 要求更大的东西只会导致错误或NaN。 实际上这完全没问题,因为在实践中你很少需要具有完美精度的巨大因子。 通常可以使用Stirlings近似或使用其他技巧来避免冗长的计算(顺便说一下69!对于袖珍计算器来说也是一个不错的基准,因为它可能在慢速计算器上花费几秒钟)。

结论 :对于合理的输入,您的代码非常好。 如果你真的需要寻求更高的阶乘,有办法,但我想你的任务并不是真的要求它。 而且,无论你怎么做,你总是达到极限。 因此,为了使您的代码“无bug”,我会添加类似的东西

assert(number < 50 && "Sorry, this number is too big");

在计算之前。

选择较大范围的数据类型,不超过存储在变量'factorial'中的值

你应该声明它, **long long int factorial = number ;**

现在,它显示为零,因为int(此处为signed)因此对于将int数据类型存储为2byte的系统,其范围从-32568到+32567。 在修饰符“long long”的帮助下,实际上将其存储字节增加到8字节,从而产生更大的范围。

现在,如果要存储在任何变量中的值超出其范围,则它通过开始从最小范围(这里是-32568)存储的值来执行循环旋转。

而你也可以使用**unsigned long long int factorial = number ;**甚至可以使它的范围更大。 由于无符号将计算其负范围与正范围,从而导致更大的正范围。

在类或结构中尝试双或长数据类型。 您还必须相应地修改您的代码。

Factorial只会产生疯狂的大数字。 您可以尝试更广泛或可能更宽的数据类型(如long ),但这只会推迟问题。 在某些时候失败。 也许在51! ,也许是60! 我们甚至不谈1000! 这就是阶乘的本质。

当然,专门的大数字图书馆可以大大缓解这个问题。 但他们不是初学者的东西。

但是,您可以做的就是安全地找出您的程序是否达到计算机的限制,如果是这种情况则打印错误消息。 C ++提供了一种名为std::numeric_limits的机制,它告诉您数据类型可以表示的最大可能值。

这是一个基于您的代码的简单示例:

#include <iostream>
#include <limits> // needed for std::numeric_limits

using namespace std;

int main()
{
    int counter = 1;
    int number;

    cout << "Please enter a number: ";
    cin >> number;

    int factorial = number;
    while (counter != number)
    {
        if (std::numeric_limits<int>::max() / factorial < (number - counter)) {
            std::cout << "cannot handle such large numbers\n";
            return 0;
        }       
        factorial = factorial * (number - counter);
        counter++;

    }

    cout << "The factorial of " << number << "! is: " << factorial << endl;
    return 0;
}

一旦检测到错误条件,将会发生什么并不重要,而是如何检测它:

std::numeric_limits<int>::max() / factorial < (number - counter)

这可以防止整数溢出。 它在数学上等同于:

std::numeric_limits<int>::max() < factorial * (number - counter) // wrong!

但是,后一版本显然不起作用,因为factorial * (number - counter)可能已经产生溢出。 通过将右侧的乘法转换为左侧的除法,您可以优雅地避免该问题。


顺便说一句,如果用户输入一个非常大的数字,所有这些仍然没有好处。 因此,您应该在使用number之前检查std::cin的状态,如果输入无法解释为int ,则同样打印错误消息。 这使您的程序更加健壮。 如果有人输入大数字,它不会简单地崩溃或产生无意义的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM