1

私はこれをしなければなりません:

次のステートメント (n<10) を計算し、計算結果 1+1/2!+1/3!.......+1/n! を表示する繰り返しプログラムを作成します。

私がしなければならないことは階乗であることは知っていますが、反転 (^-1) であり、条件があります。float などを含める必要がありますか?

#include <stdio.h>

int getValue()
{
    int n;

    printf("Enter number: ");
    scanf("%d%*c", &n);

    return(n);
}

int factorial(int n)
{
    int i, f;

    f = 1;
    for(i=1; i<=n; i++)
    f = f * i;

    return(f);
}

void printFactorial(int f)
{
    printf("The factorial is: %d", f);
}

int main()
{
    int f = getValue();

    factorial(f);
    printFactorial();

    return(0);
}
4

6 に答える 6

3

f=1+1/2!+1/3!.......+1/n!

階乗を使用する必要はありません

これはどう ?

    double term=1.0;
    double f=1.0;

    for(i=2;i<=n;i++)
    {
     term*=1.0/i;
     f+=term;
    }
于 2013-08-15T10:36:03.893 に答える
3

さて、いくつかのオプションを検討しました。つまり、

簡単な方法:

double sum = 1;
double fact = 1;
for (int i = 2; i <= n; i++)
{
    fact *= i;
    sum += 1 / fact;
}

カハン・スム:

double sum = 1;
double fact = 1;
double correction = 0;
for (int i = 2; i <= n; i++)
{
    fact *= i;
    double y = (1 / fact) - correction;
    double t = sum + y;
    correction = (t - sum) - y;
    sum = t;
}

有理和:

double numerator = 1;
double denominator = 1;
for (int i = 2; i <= n; i++)
{
    numerator = numerator * i + 1;
    denominator = denominator * i;
}
double result = numerator / denominator;

単純な方法と Kahan Sum で同じ結果が得られました。どうやら階乗駆動は逆数が非常に速く減少するため、 の後に何かの結果を合計するものは何も残っていませんn = 16

有理和はわずかに異なる答えを出しましたが (正確さは少し劣ります)、私のテストでは少し速かったです。

于 2013-08-15T10:57:43.023 に答える
1

sum_(i=1)^(n) (1/(i!)) を計算する必要がありますよね?

すべての有理数 (double である必要があります) を合計するために 1 つの for ループを実行します。そして、分母を計算し、その後、1/分母の除算を行うための for ループが 1 つずつあります。

そのように:

f=0;
for(i=1;i<=n;i++)
{
    denominator = 1; // sorry initialized first time with zero...
    for(j=1;j<=i;j++) denominator *= j;
    f+= 1/(double)denominator;
}
于 2013-08-15T10:20:22.737 に答える
0

あなたはほとんど階乗部分を持っていました。ただする必要があった

printFactorial(factorial(f));

しかし、「f=1+1/2!+1/3!.......+1/n!」に到達するには、再帰的な解決策をお勧めします。最初に最小の項を合計すると、より良い数値結果が得られます。

 #include <stdio.h>

double JAceHelper(double Factorial, int i, int n) {
  if (i >= n) {
    return 0.0;
    }
  i++;
  return 1/Factorial + JAceHelper(Factorial * i, i, n);
}

// For f=1+1/2!+1/3!.......+1/n!
double JAce(int n) {
  if (n < 0) return 1.0;  // error
  if (n < 1) return 1.0;
  return JAceHelper(1.0, 1, n);
}

int main() {
  int n;
  printf("Enter number: ");
  scanf("%d%*c", &n);
  printf("Sum is %20.15lf\n", JAce(n));
  return (0);
}
于 2013-08-16T03:28:28.100 に答える
0

最も単純なソリューションでは、浮動小数点を使用します。

精度を向上させたい場合は、最初に最小の項を合計する必要があります。これを行うために再帰的なソリューションを他の場所に投稿しましたが、単純な非再帰的なソリューションが続き、別の一般的な回答と比較されます。

2 つの方法 (float を使用) を double を使用した同じ方法 (図示せず) と比較して、相対誤差を決定しました。「最小項を最初に合計する」は、「最大項を最初に合計する」に勝ることはありませんでした。

注:
1+1/2!+1/3!.......+1/n! = (( (((1/n + 1)/(n-1) + 1)/(n-2) + 1) ... )/2 + 1/1

float f1(int n) {  // sum smallest terms together first
  float sum = 0.0;
  while (n >= 1) {
    sum = (1.0f + sum) / n;
    n--;
  }
  return sum;
}

float f2(int n) { // sum largest terms together first
  float term = 1.0;
  float f = 1.0;
  int i;
  for (i = 2; i <= n; i++) {
    term *= 1.0f / i;
    f += term;
  }
  return f;
}

void ftest(int n) {
  double y = (d1(n) + d2(n))/2;  // d1,d2 is a double version of f1,f2 (not shown)
  printf("f1 %2d %.8e %+e\n", n, f1(n), (f1(n) - y)/y);
  printf("f2 %2d %.8e %+e\n", n, f2(n), (f2(n) - y)/y);
}

int main() {
  int i;
  for (i = 5; i < 9; i++)
    ftest(i);
  return 0;
}

f1  5 1.71666670e+00 +1.851795e-08  // The exact answer is 1.716666...
f2  5 1.71666658e+00 -5.092436e-08
f1  6 1.71805549e+00 -4.008979e-08
f2  6 1.71805549e+00 -4.008979e-08
f1  7 1.71825397e+00 +1.101240e-09
f2  7 1.71825385e+00 -6.827691e-08
f1  8 1.71827877e+00 -2.422694e-09
f2  8 1.71827865e+00 -7.179985e-08
于 2013-08-19T17:38:38.177 に答える