无法计算大于20的阶乘! ! 怎么办?

我使用无符号长整数格式来计算大因子。 但是我的代码在某些时候失败了你能看一下吗? 实际上它是指数函数的泰勒展开的更大代码的一部分,但是这一部分在这一点上是无关紧要的。 我将不胜感激任何建议。

谢谢

#include  #include  //We need to write a factorial function beforehand, since we //have factorial in the denominators. //Remembering that factorials are defined for integers; it is //possible to define factorials of non-integer numbers using //Gamma Function but we will omit that. //We first declare the factorial function as follows: unsigned long long factorial (int); //Long long integer format only allows numbers in the order of 10^18 so //we shall use the sign bit in order to increase our range. //Now we define it, unsigned long long factorial(int n) { //Here s is the free parameter which is increased by one in each step and //pro is the initial product and by setting pro to be 0 we also cover the //case of zero factorial. int s = 1; unsigned long long pro = 1; if (n = s) { printf("%d \n", s); pro *= s; s++; printf("%llu \n", pro); } return pro; } } int main () { int x[12] = { 1, 5, 10, 15, 20, 100, -1, -5, -10, -20, -50, -100}; //Here an array named "calc" is defined to store //the values of x. unsigned long long k = factorial(25); printf("%llu \n", k); //int k; ////The upper index controls the accuracy of the Taylor Series, so ////it is suitable to make it an adjustable parameter. //int p = 500; //for ( k = 0; k < p; k++); } 

无符号多头的限制为18446744073709551615,即约1.8e + 19。 20! 约为2.4e + 18,所以在范围内,不过21! 约为5.1e + 19,超过无符号长长的最大尺寸。

您可能会发现这很有用: C ++中是否存在大于long long int的类型?

你的整数类型溢出了。 对于你来说, unsigned long long可能是64位长。

  • 20! 是适合的0x21c3_677c_82b4_0000
  • 21! 是0x2_c507_7d36_b8c4_0000 ,不合适。

您可以查看像GMP这样的库,它可以实现任意大整数。


扩展GMP评论。 以下是一些使用GMP计算阶乘的代码:

 void factorial(unsigned long long n, mpz_t result) { mpz_set_ui(result, 1); while (n > 1) { mpz_mul_ui(result, result, n); n = n-1; } } int main() { mpz_t fact; mpz_init(fact); factorial(100, fact); char *as_str = mpz_get_str(NULL, 16, fact); printf("%s\n", as_str); mpz_clear(fact); free(as_str); } 

这将计算factorial(100) ,并导致:

 0x1b30964ec395dc24069528d54bbda40d16e966ef9a70eb21b5b2943a321cdf10391745570cca9420c6ecb3b72ed2ee8b02ea2735c61a000000000000000000000000 

只是为了好玩,这是C ++版本。 构造函数,析构函数和运算符重载往往使这些东西的C ++版本看起来更清晰。 结果与以前相同。

 #include  #include  int main() { mpz_class fact = 1; for (int i=2; i<=100; ++i) fact *= i; std::cout << "0x" << fact.get_str(16) << "\n"; } 

unsigned long long范围通常为02 ^ 18,446,744,073,709,551,61518,446,744,073,709,551,615 )。 21! 超出这个范围。

确实:

 2^64 = 18446744073709551616 21! = 51090942171709440000 20! = 2432902008176640000 

顺便说一下,要计算一系列的结果(例如泰勒),你不应该分别计算每个术语; 这肯定会带给你这样的问题。 相反,尝试通过重用前一个术语来计算每个术语。

例如, cos的泰勒级数需要以下项的总和:

 (-1)^i * (x^(2*i)) / (2i)! 

很容易看出,每个术语都可以从前一个术语轻松计算出来:

 newterm = - oldterm * x^2 / ((2i+1)*(2i+2)) 

因此,我认为您不需要计算大因子,因为您正在尝试做什么。 另一方面,如果你需要,你将不得不使用一个大数字库,如gmp

factorial(25)应该给出结果18,446,744,073,709,551,615,它大于unsigned long long 数据类型范围的范围

长长的只是如此之大,因此只能代表如此大的数字。 如果你需要一个更大整数的精确表示,你需要使用其他东西(一些你自己制作的第三方库或某种数据类型); 如果你不需要它是准确的,那么你可以改用double。

我写的一个简单的算法。 但它是用Java编写的。你可以在大约15分钟内计算出1000的阶乘。

该算法与我们在小学学习的基本公式一起使用。

 /* FOR BEST RESULT DON'T CHANGE THE CODE UNTIL YOU KNOW WHAT YOU'RE DOING */ public String factorial(int number){ if(number == 0) return "1"; String result = "1"; for(int i = 0; i < number; i++){ result = *longNumberMultiplyingAlgorithm*(result, "" + (i + 1)); } return result; } public String longNumberMultiplyingAlgorithm(String number1, String number2){ int maxLength = Math.max(number1.length(), number2.length()); int a = 0; String[] numbers = new String[maxLength]; if(number2.length() > number1.length()){ String t = number1; number1 = number2; number2 = t; } for(int i = 0; i < number1.length(); i++){ numbers[i] = ""; a = 0; for(int j = 0; j < number2.length(); j++){ int result = Integer.parseInt(String.valueOf(number1.charAt(number1.length() - i - 1))) * Integer.parseInt(String.valueOf(number2.charAt(number2.length() - j - 1))); if(result + a < 10){ numbers[i] = (result + a) + "" + numbers[i]; a = 0; }else{ result += a; a = (int)((result + 0.0) / 10); result -= a * 10; numbers[i] = result + "" + numbers[i]; } } if(a != 0){ numbers[i] = a + "" + numbers[i]; } for(int k = 0; k < i; k++){ numbers[i] += "0"; } } return longNumberAdditionAlgorithm(numbers); } private String longNumberAdditionAlgorithm(String[] numbers) { String final_number = "0"; for(int l = 0; l < numbers.length; l++){ int maxLength = Math.max(final_number.length(), numbers[l].length()); String number = ""; int[] n = new int[maxLength]; int a = 0; for(int i = 0; i < n.length; i++){ int result = 0; if(i >= final_number.length()){ result = Integer.parseInt(String.valueOf(numbers[l].charAt(numbers[l].length() - i - 1))); }else if(i >= numbers[l].length()){ result = Integer.parseInt(String.valueOf(final_number.charAt(final_number.length() - i - 1))); }else{ result = Integer.parseInt(String.valueOf(final_number.charAt(final_number.length() - i - 1))) + Integer.parseInt(String.valueOf(numbers[l].charAt(numbers[l].length() - i - 1))); } if(result + a < 10){ number = (result + a) + "" + number; a = 0; }else{ result -= 10; number = (result + a) + "" + number; a = 1; } } if(a == 1){ number = a + "" + number; } final_number = number; } return final_number; }