c++ 阶乘函数给出负数

am46iovg  于 2023-07-01  发布在  其他
关注(0)|答案(2)|浏览(1489)

所以我用c++写了一个程序,假设从1开始无休止地打印数字的阶乘。它打印了第一个一些数字,如预期的正确阶乘值,但在此之后,它只是最终得到负值和程序被终止,由于条件提到。但我不确定一个好的阶乘程序如何最终得到负值。

#include<iostream>
using namespace std;
int main(){
    int a = 1;
    int c = 1;
    while(a>0){
        cout<<(a*c)<<endl;
       
        a = a*c;
        c = c+1;
    }
    return 0;
}

我期望阶乘的结果从1到永远是无穷的。
结果我得到了-

1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
1932053504
1278945280
2004310016
2004189184 //Number Decreased Instead of Increasing
-288522240 //Now It is negative
xqk2d5yq

xqk2d5yq1#

int是有符号类型。阶乘变得足够大,以至于溢出(超过int可以存储的最大值)。当他们这样做时,你开始看到似乎没有意义的答案。
这可以通过一个简单的演示程序很容易地看到:

$ cat test.cpp
#include <iostream>
#include <iomanip>
#include <limits.h>

int factorial(int n) {
    int result = 1;
    for (; n > 1; n--) result *= n;
    return result;
}

int main() {
    for (int i = 1; i < 20; i++) {
        std::cout << std::setw(10) << std::right
                  << factorial(i) << std::endl
                  << INT_MAX << " <- max " << std::endl;
    }
}
$ g++ test.cpp
$ ./a.out
         1
2147483647 <- max
         2
2147483647 <- max
         6
2147483647 <- max
        24
2147483647 <- max
       120
2147483647 <- max
       720
2147483647 <- max
      5040
2147483647 <- max
     40320
2147483647 <- max
    362880
2147483647 <- max
   3628800
2147483647 <- max
  39916800
2147483647 <- max
 479001600
2147483647 <- max
1932053504
2147483647 <- max
1278945280
2147483647 <- max
2004310016
2147483647 <- max
2004189184
2147483647 <- max
-288522240
2147483647 <- max
-898433024
2147483647 <- max
 109641728
2147483647 <- max

如果你想看到更大的阶乘结果,你需要使用更大的整数类型,可能是更大的 unsigned 整数类型。
如果我们这样做,我们为自己购买了一些额外的空间来生成更大的阶乘。

$ cat test.cpp
#include <iostream>
#include <iomanip>

unsigned long long int factorial(int n) {
    unsigned long long int result = 1;
    for (; n > 1; n--) result *= n;
    return result;
}

int main() {
    for (int i = 1; i < 20; i++) {
        std::cout << std::setw(19) << std::right
                  << factorial(i) << std::endl
                  << ULONG_LONG_MAX << " <- max " << std::endl;
    }
}
$ g++ test.cpp
$ ./a.out
                  1
9223372036854775807 <- max
                  2
9223372036854775807 <- max
                  6
9223372036854775807 <- max
                 24
9223372036854775807 <- max
                120
9223372036854775807 <- max
                720
9223372036854775807 <- max
               5040
9223372036854775807 <- max
              40320
9223372036854775807 <- max
             362880
9223372036854775807 <- max
            3628800
9223372036854775807 <- max
           39916800
9223372036854775807 <- max
          479001600
9223372036854775807 <- max
         6227020800
9223372036854775807 <- max
        87178291200
9223372036854775807 <- max
      1307674368000
9223372036854775807 <- max
     20922789888000
9223372036854775807 <- max
    355687428096000
9223372036854775807 <- max
   6402373705728000
9223372036854775807 <- max
 121645100408832000
9223372036854775807 <- max
jv4diomz

jv4diomz2#

标准的C++整数类型有一个定义的范围值,以便保持在由架构定义的位数(32位,64位等)。您可以通过搜索min and max values for types(它可能取决于体系结构)或使用更现代的东西(如numeric_limits class template)来检查它们。
如果你计算一个更大(或更小)的数字,你会有一个整数溢出,这是由于进程中数字运算的逻辑实现。你可以有不确定的行为,或有趣的附带影响。一种典型的行为(感谢@Aconcagua)行为可能是应用程序崩溃。
如果你需要处理比这个更大的数字,你应该依赖一个专用的库,比如boost::multiprecision,它有表示任意大小的数字的类。注意,显然因为数字较大,它们以库逻辑定义的特殊方式处理,并且通常比内置类型慢。如果它可能是一个问题取决于你和你的应用程序的性能要求。

相关问题