我使用无符号长整数格式来计算大因子。但是我的代码在某些时候失败了你能看一下吗?实际上它是指数函数的泰勒展开的更大代码的一部分,但是这一部分在这一点上是无关紧要的。我将不胜感激任何建议。
由于
#include <stdio.h>
#include <math.h>
//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 < 0)
printf("Factorial is not defined for a negative number \n");
else {
while (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++);
}
答案 0 :(得分:15)
无符号多头的限制是18446744073709551615,或约1.8e + 19。 20!约为2.4e + 18,因此在范围内,不过21!约为5.1e + 19,超过无符号长长的最大尺寸。
答案 1 :(得分:7)
你的整数类型溢出了。 unsigned long long
可能是64位长。
0x21c3_677c_82b4_0000
适合。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 <gmpxx.h>
#include <iostream>
int main() {
mpz_class fact = 1;
for (int i=2; i<=100; ++i)
fact *= i;
std::cout << "0x" << fact.get_str(16) << "\n";
}
答案 2 :(得分:5)
unsigned long long
的范围通常为 0 至 2 ^ 64 - 1 (18,446,744,073,709,551,615
)。 21!超出这个范围。
答案 3 :(得分:4)
事实上:
2^64 = 18446744073709551616
21! = 51090942171709440000
20! = 2432902008176640000
顺便说一下,要计算一系列的结果(例如泰勒),你不应该分别计算每个词;这肯定会带给你这样的问题。相反,尝试通过重复使用前一个术语来计算每个术语。
例如,cos
的泰勒系列需要以下术语的总和:
(-1)^i * (x^(2*i)) / (2i)!
很容易看出,每个术语都可以从前一个术语轻松计算出来:
newterm = - oldterm * x^2 / ((2i+1)*(2i+2))
所以,我相信你不需要计算大因子,因为你正在尝试做什么。另一方面,如果需要,您将不得不使用大型数据库,例如gmp
。
答案 4 :(得分:2)
factorial(25)应给出结果18,446,744,073,709,551,615,其大于无符号长long Data Type Ranges
的范围答案 5 :(得分:2)
长长的只是如此之大,因此只能代表如此大的数字。如果你需要一个更大整数的精确表示,你需要使用其他东西(一些你自己制作的第三方库或某种数据类型);如果你不需要它,那么你可以改用double。
答案 6 :(得分:0)
我写的一个简单的算法。但是它在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;
}