指数関数について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
初心者プログラマー
記事: 3
登録日時: 4年前

指数関数について

#1

投稿記事 by 初心者プログラマー » 4年前

指数関数e^tをテイラー展開で各点で計算し、expと比較するというプログラムについて、実行結果がnanになってしまいます。どこを改善すればよいでしょうか。

コード:

#include <stdio.h>
#include <math.h>
double taylor_exp( int, double );

int main(void){
    int k_max = 15;
    int sample = 8;
    int n,m;
    n = k_max + 2;
    m = sample + 1;
    double data[n][m];
    double data_exp[m];
    int i,j;
    double pi=3.141592;
    double td=((2.0*pi)/(double)sample);
    for(j=0;j<m;j++)
    data[0][j] = td*j;
    for(j=0;j<m;j++)
    data_exp[j] = exp(data[0][j]);
    for(i=1;i<k_max+1;i++)
    for(j=0;j<m;j++){
        data[i][j]=taylor_exp( i, data[0][j] );
        data[i+1][j]=data[i][j]-data_exp[j];
    }
    printf("       t = ");
    for(j=0;j<m;j++)
    printf("%8.4f",data[0][j]);
    printf("\n\n");
    
    for(i=1;i<n;i+=2){
        printf("%2dth exp = ",i);
        for(j=0;j<m;j++)
        printf("%8.4f",data[i][j]);
        printf("\n");
        printf("%2dth err = ",i);
        for(j=0;j<m;j++)
        printf("%8.4f",data[i+1][j]);
        printf("\n\n");
    }
    
    return 0;
    
}
double taylor_exp( int i, double t ){
    double z;
    double zk;
    int k;
    zk=1;
    z+=zk;
    for(k=2;k<i+1;k++){
        zk*=(((-1)/((k-1)*k))*t);
        z+=zk;
    }
    
    return z;
    
}

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

Re: 指数関数について

#2

投稿記事 by みけCAT » 4年前

Wandboxで実行した結果は

コード:

       t =   0.0000  0.7854  1.5708  2.3562  3.1416  3.9270  4.7124  5.4978  6.2832

 1th exp =   7.2832  8.2832  9.2832 10.2832 11.2832 12.2832 13.2832 14.2832 15.2832
 1th err =  16.2832 17.2832 18.2832 19.2832 20.2832 21.2832 22.2832 23.2832 24.2832

 3th exp =  25.2832 26.2832 27.2832 28.2832 29.2832 30.2832 31.2832 32.2832 33.2832
 3th err =  34.2832 35.2832 36.2832 37.2832 38.2832 39.2832 40.2832 41.2832 42.2832

 5th exp =  43.2832 44.2832 45.2832 46.2832 47.2832 48.2832 49.2832 50.2832 51.2832
 5th err =  52.2832 53.2832 54.2832 55.2832 56.2832 57.2832 58.2832 59.2832 60.2832

 7th exp =  61.2832 62.2832 63.2832 64.2832 65.2832 66.2832 67.2832 68.2832 69.2832
 7th err =  70.2832 71.2832 72.2832 73.2832 74.2832 75.2832 76.2832 77.2832 78.2832

 9th exp =  79.2832 80.2832 81.2832 82.2832 83.2832 84.2832 85.2832 86.2832 87.2832
 9th err =  88.2832 89.2832 90.2832 91.2832 92.2832 93.2832 94.2832 95.2832 96.2832

11th exp =  97.2832 98.2832 99.2832100.2832101.2832102.2832103.2832104.2832105.2832
11th err = 106.2832107.2832108.2832109.2832110.2832111.2832112.2832113.2832114.2832

13th exp = 115.2832116.2832117.2832118.2832119.2832120.2832121.2832122.2832123.2832
13th err = 124.2832125.2832126.2832127.2832128.2832129.2832130.2832131.2832132.2832

15th exp = 133.2832134.2832135.2832136.2832137.2832138.2832139.2832140.2832141.2832
15th err = 132.2832132.0899130.4727125.7325114.1425 87.5292 27.9655-103.8676-394.2078
となり、「実行結果がnanになってしまいます」というのは確認できませんでした。
ただし、taylor_exp関数内で、未初期化の自動変数zの値が計算に使われており、未定義動作になります。
この変数を初期化してから計算するようにすると、改善するかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: 指数関数について

#3

投稿記事 by かずま » 4年前

taylor_exp が変です。
z が未初期化である以外に、
(-1)/((k-1)+k) が整数の割り算で常に 0 になっています。
zk *= -t / ((k-1) * k); と書いたほうが良いのでは?

i が 5 だとすると、k = 2, 3, 4, 5 だから、

z = 1 - t/(1*2) + t2/(1*2*2*3) - t3/(1*2*2*3*3*4) + t4/(1*2*2*3*3*4*4*5)

やっぱり変です。

et のテイラー展開なら次のようになるのではありませんか?

コード:

double taylor_exp(int i, double t)
{
	double z = 1, zk = 1;
	for (int k = 1; k < i; k++)
		zk *= t / k, z += zk;
	return z;
}

返信

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