誕生日にもらった意外なもの

最近c言語を勉強し始めたのですが解決できない問題が出来たので質問です。 入力された整数nに対して Σ{i=0→n} 1/i! を計算するプログラムなんですがわかる方がいたらよろしくお願いします。

A 回答 (7件)

プログラムというより、どちらかというと数学の問題ですね。



Σ{i=0→n} 1/i! の値はよく知られているように、nが無限大の時にネイピア数(自然対数の底)eになります。

nがある値以上の場合には有効桁数が溢れて演算が無効になりますからその時はeを返せばよいということです。
有効桁数が溢れて演算が無効になるnをn_MAXとおくと、

#include <math.h>

if (n > n_MAX) return(M_E);

となります。M_Eはコンパイラが提供するネイピア数です。n_MAXは処理系固定なので予めプリプロセッサで計算しておくか、定義しておきます。

つぎに計算量を小さくする工夫が必要です。上記のようにn_MAXを求めておいた場合には
nがn_MAXに近い場合には減算した方が速いので処理を分離します。

// n_MAX!は予め計算しておくこと
#define fact_MAX = 1.0/(double)(n_MAX!);

if (n > (n_MAX - n)) {
double s, fact;
int i;

// s = Σ{i=n+1 → n_MAX} 1/i! の計算
s = fact = fact_Max;
for (n += 1, i = n_MAX; i > n ; i--) {
fact *= (double)i;
s += fact;
}
return(M_E - s);
}

以下は他の回答者の方を参考にしてみてください。
    • good
    • 0
この回答へのお礼

お礼が遅れてしまい申し訳ありません。
みなさんのおかげでなんとか解決する事ができました。
まだこれからもC言語を勉強していくつもりなので壁に当たった時はよろしくおねがいします。m(_ _)m

お礼日時:2010/07/31 21:34

#include <stdio.h>



int main(void)
{
double s;
int n, f, i;

do {
printf("n="), scanf("%d", &n);
} while (0 > n || n > 33);
for (s = f = i = 1; i <= n; i++) {
s += 1. / (f *= i);
}
printf("%.15f\n", s);
return 0;
}
    • good
    • 0

>それにnを掛ければよいだけですね。



nを、よりは「次の数を」と書いた方がより正確だったかもしれません。
    • good
    • 0

0!の逆数を合計に足し込む。


1!の逆数を合計に足し込む。
2!の逆数を合計に足し込む。
...
n!の逆数を合計に足し込む。

のように、0~nについて毎回階乗を求めるのは
ひじょうに効率が悪いです。
nが1以上のときの階乗は、それより1個前の階乗(初期値は0!=1)を
すでに求めているのですから、それにnを掛ければよいだけですね。
    • good
    • 0
この回答へのお礼

お礼が遅れてしまい申し訳ありません。
みなさんのおかげでなんとか解決する事ができました。
まだこれからもC言語を勉強していくつもりなので壁に当たった時はよろしくおねがいします。m(_ _)m

お礼日時:2010/07/31 21:35

>入力された整数n



整数を入力させる方法はわかっていますか?
わからなければ、本読んだり、ここの他の質問を読んでみるなりして調べてみてください。

でも、とりあえず、
int n ;
n=10 ;
とかして、数値入れておいて、数値変えるたびにコンパイルすれば、Σの部分の確認はできます。
あとまわしでいいです。


> Σ{i=0→n} 1/i!

どんな式でも受けつけるΣを計算するような関数は標準では用意されていません。
ですので、Σの意味を考えてプログラムで実現します。

関数f(i)について
Σ(i=0→n) f(i) =f(0)+f(1)+...+f(n)
ですよね?
これは
a=0;
i=0 ; a += f(i);
i=1 ; a += f(i);
...
i=n ; a += f(i) ;
とした後の aの値ですよね?
任意のnについて上の計算をするとして、便利な命令がCにはあった筈です。よく思い出してみましょう。

また、
n! = 1 (n=0のとき) , (n-1)! * n (n>0のとき)
というのも覚えてますか?


注意点として、 Cでは 整数÷整数は整数(小数点以下切り捨て)になる、ということです。
1/i! を 双方int型のままで計算しようとすると、 0か1にしかなりません。
このような場合は、型変換を利用して、実数型(精度を考えれば、doubleがよい)にします。
    • good
    • 0
この回答へのお礼

お礼が遅れてしまい申し訳ありません。
みなさんのおかげでなんとか解決する事ができました。
まだこれからもC言語を勉強していくつもりなので壁に当たった時はよろしくおねがいします。m(_ _)m

お礼日時:2010/07/31 21:35

分からない・知らないことは何ですか?


- 問題の数式の意味
- C言語で足し算や割り算を行う方法
- C言語でn回ループする方法
- その他
i! (iの階乗)の計算はかけ算とループを知っていれば書けます。

途中まででもいいので、質問者さんが書いたプログラムを示してみてください。
    • good
    • 0
この回答へのお礼

お礼が遅れてしまい申し訳ありません。
みなさんのおかげでなんとか解決する事ができました。
まだこれからもC言語を勉強していくつもりなので壁に当たった時はよろしくおねがいします。m(_ _)m

お礼日時:2010/07/31 21:35

nが3とか4くらいの小さい値のとき、


手で計算するとしたらどういう風にするかを実験してから、
nが一般の値をとる場合をソースコードに落とし込んではいかがでしょう。
    • good
    • 0
この回答へのお礼

お礼が遅れてしまい申し訳ありません。
みなさんのおかげでなんとか解決する事ができました。
まだこれからもC言語を勉強していくつもりなので壁に当たった時はよろしくおねがいします。m(_ _)m

お礼日時:2010/07/31 21:34

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!