e^2xをマクローリン展開する

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
t_n_y_09
記事: 8
登録日時: 11ヶ月前

e^2xをマクローリン展開する

#1

投稿記事 by t_n_y_09 » 11ヶ月前

大学の課題が解けません。
デバッグはできるのですが数字が合いません。
どこが違うか教えてください。

問題
e^2xをマクローリン展開し、有効数字10桁まで求めよ。


この時の有効数字は、展開したk-1の項までの和と、k項までの和が10桁一致するまでループするということです。
k項までの和-k項までの和は、k項であると思ったので、k項×10^10が0以下になるまでループしました。

コード: 全て選択

#define _CRT_SECURE_NO_WARNINGS 1
#define _USE_MATH_DEFINES
#include<stdio.h>
#include <math.h>

int main(void) {
	double x;
	int kai = 1;
	int k;
	int i;//階乗に使う
	double bb;//2*x
	double bb2;//分母
	double kou;//k項
	double ans;//2項からk項までの和
	double sa;//最後の項

	printf("e^2xのxをいくつにしますか?\n");//e^2xの入力
	scanf("%lf", &x);
	bb = 2 * x;
	ans = 1.0;
	for (k = 1;; k += 1)//kを増やす
	{
		bb2 = pow(bb, k);//2x^k
		for (i = 1; i <= k; ++i) {//階乗
			kai = kai * i;
		};

		kou = bb2 / kai;//k項
		sa = kou * 10000000000;

		if (sa <= 0)
			break;//差が0以下になったらこのループを終わりにする。

		ans = ans + kou;
	}
printf("計算結果は%fです\n", ans);//出力⑨

	return 0;
}
[実行結果]
e^2のxを何にしますか?
5(入力)
計算結果は182.000927です

かずま

Re: e^2xをマクローリン展開する

#2

投稿記事 by かずま » 11ヶ月前

t_n_y_09 さんが書きました:デバッグはできるのですが数字が合いません。
どこが違うか教えてください。
bb2 = pow(bb, k); を
bb2 = pow(bb, 2 * k); にする。

別解

コード: 全て選択

#include <stdio.h>

int main(void)
{
    double x;
    while (printf("x: "), scanf("%lf", &x) == 1) {
        double y = 1, t = 1;
        for (int k = 1; y != y - t; k++)
            y += t *= 2 * x / k;
        printf("%.15g\n", y);
    }
    return 0;
}

かずま

Re: e^2xをマクローリン展開する

#3

投稿記事 by かずま » 11ヶ月前

かずま さんが書きました:bb2 = pow(bb, k); を
bb2 = pow(bb, 2 * k); にする。
すみません。この指摘は間違いです。
(2 * x) を k乗しないといけないのにしていないなあ、と勘違いしました。
bb が (2 * x) だったんですね。
終了条件がおかしいようなので、もう少し調べてみます。

かずま

Re: e^2xをマクローリン展開する

#4

投稿記事 by かずま » 11ヶ月前

kai がオーバーフローしています。
int kai = 1; を double kai; にしてください。

kai の初期化は、for文で行います。
for (kai = k = 1; ; k++)

終了条件は、if (ans + kou == ans) break; です。
kou は ゼロにはなりませんが、かなり小さくなります。
すると、ans + kou で桁落ちして、結果が ans になります。
sa は不要です。

アバター
みけCAT
記事: 6003
登録日時: 7年前
住所: 千葉県
連絡を取る:

Re: e^2xをマクローリン展開する

#5

投稿記事 by みけCAT » 11ヶ月前

しまった、二重投稿でしたか。
e^2xをマクローリン展開する • C言語交流フォーラム ~ mixC++ ~
みけCAT さんが書きました:
  • 各繰り返しにおいて、kaiに1からkまでの整数全てを掛けるのではなく、kだけを掛ける
  • kaiの型をintからdoubleにする
という変更を加えた所、x=5の時の計算結果が合いました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6003
登録日時: 7年前
住所: 千葉県
連絡を取る:

Re: e^2xをマクローリン展開する

#6

投稿記事 by みけCAT » 11ヶ月前

かずま さんが書きました:kai の初期化は、for文で行います。
for (kai = k = 1; ; k++)
それはなぜですか?
宣言時のみに初期化をしても、間違いではないでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: e^2xをマクローリン展開する

#7

投稿記事 by かずま » 11ヶ月前

みけCAT さんが書きました:
かずま さんが書きました:kai の初期化は、for文で行います。
for (kai = k = 1; ; k++)
それはなぜですか?
すみません。修正方法の書き方に間違いがありました。

for文は、for (k = 1; ... と for (i = 1; ... の 2つあって、
後者を for (kai = i = 1; 修正するのですが、
回答を書くとき、間違って for (kai = k = 1; と
書いてしまいました。正しくは、24行目を
for (kai = i = 1; i <= k; ++i) {//階乗
にする、です。
みけCAT さんが書きました: 宣言時のみに初期化をしても、間違いではないでしょう。
kai の宣言は main の最初のほうにありますが、
第k項の kai を求める for文で初期化しないと、
第(k-1)項の kai にさらに k の階乗を掛けることになって
間違った結果になります。

アバター
みけCAT
記事: 6003
登録日時: 7年前
住所: 千葉県
連絡を取る:

Re: e^2xをマクローリン展開する

#8

投稿記事 by みけCAT » 11ヶ月前

かずま さんが書きました:
みけCAT さんが書きました: 宣言時のみに初期化をしても、間違いではないでしょう。
kai の宣言は main の最初のほうにありますが、
第k項の kai を求める for文で初期化しないと、
第(k-1)項の kai にさらに k の階乗を掛けることになって
間違った結果になります。
自分が書いたように、変数宣言の所で初期化をしてkのループ内ではkaiにkの階乗ではなくkを掛けるようにすることで、
正しい結果を得つつ、毎回階乗を計算するよりステップ数を減らすことができます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: e^2xをマクローリン展開する

#9

投稿記事 by かずま » 11ヶ月前

みけCAT さんが書きました:自分が書いたように、変数宣言の所で初期化をしてkのループ内ではkaiにkの階乗ではなくkを掛けるようにすることで、
正しい結果を得つつ、毎回階乗を計算するよりステップ数を減らすことができます。
第k項は (2x)k / k! です。
質問者の t_n_y_09さんは、これをそのままコード化しようとしたんでしょう。

コード: 全て選択

    bb = 2 * x;
    for (k = 1; ; k += 1) {
        bb2 = pow(bb, k);
        kai = factorial(k);
        kou = bb2 / kai;
階乗の関数 factorial はないから、forループを使った。

みけCATさんは、一つ前の項の計算で使用した kai を使えば
ステップ数が減らせるとして、次のようにした。

コード: 全て選択

    double kai = 1;
    bb = 2 * x;
    for (k = 1; ; k += 1) {
        bb2 = pow(bb, k);
        kai *= k;
        kou = bb2 / kai;
それなら、pow も使わないほうが良いでしょう。

コード: 全て選択

    double bb2 = 1;
    double kai = 1;
    bb = 2 * x;
    for (k = 1; ; k += 1) {
        bb2 *= bb;
        kai *= k;
        kou = bb2 / kai;
さらに、次のようにすることができます。

コード: 全て選択

    double kou = 1;
    bb = 2 * x;
    for (k = 1; ; k += 1) {
        kou *= bb2 / k;
私は、最初の回答の別解でこれを示しました。

コード: 全て選択

    double y = 1, t = 1;  // y は元の ans。t は term(項) で、元の kou
    for (int k = 1; y != y - t; k++)
        y += t *= 2 * x / k;  // 2 * x は bb のように一つの変数にしたほうがよいかな?
終了条件を、t がゼロになるまでとすると、k = 171 になります。
y が一つ前の y と等しくなるまでとすると、k = 46 になって、
ステップ数が大きく減少します。x = 5 の場合ですが。

かずま

Re: e^2xをマクローリン展開する

#10

投稿記事 by かずま » 11ヶ月前

かずま さんが書きました: さらに、次のようにすることができます。

コード: 全て選択

    double kou = 1;
    bb = 2 * x;
    for (k = 1; ; k += 1) {
        kou *= bb2 / k;
すみません。最後の行は kou *= bb / k; の間違いです。
t_n_y_09 さんが書きました:問題
e^2xをマクローリン展開し、有効数字10桁まで求めよ。
有効数字10桁ですから、

コード: 全て選択

#define _CRT_SECURE_NO_WARNINGS 1
#define _USE_MATH_DEFINES

#include <stdio.h>
#include <math.h>
 
int main(void)
{
    int k;
    double x;        // 入力
    double kai = 1;  // k! (k の階乗。第k項の分母)
    double bb;       // 2*x
    double bb2 = 1;  // (2*x)^k (第k項の分子)
    double kou;      // 第k項
    double ans = 1;  // 第k項までの和
 
    printf("e^2xのxをいくつにしますか?\n");
    scanf("%lf", &x);
    bb = 2 * x;
    for (k = 1; ; k++) {
        bb2 *= bb;
        kai *= k;
        kou = bb2 / kai;
        ans += kou;
#if 0
        printf("%3d: bb2=%6g, kai=%-12g, kou=%-12g, ans=%-19.18g\n",
                k, bb2, kai, kou, ans);
#endif
        if (kou * 1e10 < ans) break;
    }
    printf("計算結果は %.10g です\n", ans);
    return 0;
}
#if 0 を #if 1 にすると、デバッグ表示が出ます。

かずま

Re: e^2xをマクローリン展開する

#11

投稿記事 by かずま » 10ヶ月前

No.10 のプログラムでは、x = 45.53 までは大丈夫ですが、
それを超えるとbb2 が浮動小数点の最大値を超え、
無限ループになるようです。

次のようにすると、x = 354 まで大丈夫で、それを超えても
結果が無限大になるだけで、無限ループにはなりません。

コード: 全て選択

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
 
int main(void)
{
    double x;
    puts("e^2xのxをいくつにしますか?");
	if (scanf("%lf", &x) != 1) return 1;
	double sum = 1, term = 1, x2 = 2 * x;
    for (int k = 1; term * 1e10 > sum; k++)
        sum += term *= x2 / k;
    printf("計算結果は %.10g です\n", sum);
    return 0;
}
pow を使わないので、#include <math.h> は要りません。

質問者は、なぜ返信してこないのだろうか?

t_n_y_09
記事: 8
登録日時: 11ヶ月前

Re: e^2xをマクローリン展開する

#12

投稿記事 by t_n_y_09 » 2ヶ月前

質問者です。返信遅れてすみません。無事成功できました。ありがとうございました。

Math

Re: e^2xをマクローリン展開する

#13

投稿記事 by Math » 2ヶ月前

[雑談]
http://dixq.net/forum/viewtopic.php?f=3&t=19911
前回の sin x の マクローリン展開(テイラー展開)と 今回の e^2x ( e^x に置き換える)にて x を 虚数 ix に置き換えると
有名な オイラーの公式を得る。
https://www.sci.hokudai.ac.jp/~inaz/lec ... node4.html

これが複素数の指数関数である。s = x + iy として e^s = e^(x + iy)=e^x * e^iy であり 複素積分によって ラプラス変換
が導かれ 電気工学、制御工学の伝達関数として用いられる。
http://dixq.net/forum/viewtopic.php?f=3&t=19769

返信

“C言語何でも質問掲示板” へ戻る