简单的 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 class。
看看这个:Thread
尝试在 class 或结构中使用 double 或 long 数据类型。您还必须相应地修改您的代码。
选择不超过变量'factorial'
中存储的值的更大范围的数据类型
您应该将其声明为,**long long int factorial = number ;**
现在,它显示为零,因为 int(这里有符号)所以对于将 int 数据类型存储为 2byte 的系统,它的范围从 -32568 到 +32567。
在修饰符 "long long" 的帮助下,您实际上将其存储字节增加到 8 个字节,从而导致更大的范围。
现在,如果要存储在任何变量中的值超出其范围,那么它将通过从最小范围(此处为 -32568)开始存储的值来执行循环旋转。
而且您还可以使用 , **unsigned long long int factorial = number ;**
甚至使其范围更大。由于 unsigned 将计算其负范围和正范围,这会导致更大的正范围。
已经有一些答案了。然而,他们都没有提供一些(恕我直言)重要的事实:
无论您选择多大的结果类型,您的程序能够计算的内容总是有限的。
在普通袖珍计算器上 69!是他们可以显示的最大阶乘(因为它是具有两位数指数的最大阶乘)。要求任何更大的东西只会导致错误或 NaN。实际上这很好,因为在实践中你很少需要如此大的精确度如此大的阶乘。通常可以使用斯特林近似或使用其他技巧来避免冗长的计算(顺便说一句,69!也是袖珍计算器的一个很好的基准,因为在较慢的计算器上它可能已经花费了几秒钟)。
结论:您的代码非常适合合理的输入。如果你真的需要更高的阶乘,有很多方法,但我想你的作业并没有真正要求它。而且,无论你怎么做,你总是会遇到一个极限。因此,为了使您的代码 "bug free" 我会添加类似
的内容
assert(number < 50 && "Sorry, this number is too big");
计算前。
阶乘只会产生非常大的数字。您可以尝试使用更宽或可能更宽的数据类型(如 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
,同样会打印一条错误消息。这使您的程序更加健壮。如果有人输入大数字,它不会简单地崩溃或产生无意义的结果。
作为家庭作业,我需要一个程序来读取一个非负整数并计算并打印它的阶乘。 到目前为止,我编写了代码,但如果我尝试输入 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 class。 看看这个:Thread
尝试在 class 或结构中使用 double 或 long 数据类型。您还必须相应地修改您的代码。
选择不超过变量'factorial'
中存储的值的更大范围的数据类型您应该将其声明为,**long long int factorial = number ;**
现在,它显示为零,因为 int(这里有符号)所以对于将 int 数据类型存储为 2byte 的系统,它的范围从 -32568 到 +32567。 在修饰符 "long long" 的帮助下,您实际上将其存储字节增加到 8 个字节,从而导致更大的范围。
现在,如果要存储在任何变量中的值超出其范围,那么它将通过从最小范围(此处为 -32568)开始存储的值来执行循环旋转。
而且您还可以使用 , **unsigned long long int factorial = number ;**
甚至使其范围更大。由于 unsigned 将计算其负范围和正范围,这会导致更大的正范围。
已经有一些答案了。然而,他们都没有提供一些(恕我直言)重要的事实:
无论您选择多大的结果类型,您的程序能够计算的内容总是有限的。
在普通袖珍计算器上 69!是他们可以显示的最大阶乘(因为它是具有两位数指数的最大阶乘)。要求任何更大的东西只会导致错误或 NaN。实际上这很好,因为在实践中你很少需要如此大的精确度如此大的阶乘。通常可以使用斯特林近似或使用其他技巧来避免冗长的计算(顺便说一句,69!也是袖珍计算器的一个很好的基准,因为在较慢的计算器上它可能已经花费了几秒钟)。
结论:您的代码非常适合合理的输入。如果你真的需要更高的阶乘,有很多方法,但我想你的作业并没有真正要求它。而且,无论你怎么做,你总是会遇到一个极限。因此,为了使您的代码 "bug free" 我会添加类似
的内容assert(number < 50 && "Sorry, this number is too big");
计算前。
阶乘只会产生非常大的数字。您可以尝试使用更宽或可能更宽的数据类型(如 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
,同样会打印一条错误消息。这使您的程序更加健壮。如果有人输入大数字,它不会简单地崩溃或产生无意义的结果。