• 締切済み

数値解析に関する質問です

以下のプログラムでは、関数pivotは,3つの引数を利用しているが,これを2つに減らす方法はないか? 教えてください。よろしくお願いします。 /*Gaussian Elimination*/ #include <stdio.h> #include <math.h> /*--------------*/ void inputdata(double [3][4]); void calsol(double [3][4],double [3]); void elimination(double[3][4],double[3][4]); void pivot(int *, double [3][4],int *); void outputdata(double [3]); void checksol(double [3][4], double [3]); /*--------------*/ main(){ double c[3][4], x[3]; /*-----------------------*/ printf("Program of Gauss Elimination\n"); /*-----------------------*/ inputdata(c); /*-----------------------*/ calsol(c,x); /*-----------------------*/ outputdata(x); /*-----------------------*/ checksol(c,x); /*-----------------------*/ return(0); } /*-----------------------*/ void inputdata(double c[3][4]){ int ie,ic; printf("------\n"); printf("Input Data\n"); printf("(a0*x0 + a1*x1 +a2*x2 = a3)\n"); printf("\n"); for(ie=0; ie<=2; ie++){ printf("Equation %d\n",ie); printf("Input a0 a1 a2 a3\n"); for(ic=0;ic<=3;ic++){ scanf("%lf", &c[ie][ic]); } } } /*-----------------------*/ void calsol(double c[3][4], double x[3]){   double cc[3][4]; elimination(c,cc); x[2]=cc[2][3]; x[1]=cc[1][3]-cc[1][2]*x[2]; x[0]=cc[0][3]-cc[0][2]*x[2]-cc[0][1]*x[1]; } /*-----------------------*/ void elimination(double c3[3][4], double cc[3][4]){ int ie,imax,eli; double c2[3][4],c1[3][4]; eli = 0; pivot (&eli,c3,&imax); cc[0][0]=1; cc[0][1]=c3[imax][1]/c3[imax][0]; cc[0][2]=c3[imax][2]/c3[imax][0]; cc[0][3]=c3[imax][3]/c3[imax][0]; for(ie=0;ie<=2;ie++){ if(ie != imax){ c2[ie][0]=0; c2[ie][1]=c3[ie][1]-cc[0][1]*c3[ie][0]; c2[ie][2]=c3[ie][2]-cc[0][2]*c3[ie][0]; c2[ie][3]=c3[ie][3]-cc[0][3]*c3[ie][0]; } } eli = 1; pivot(&eli,c2,&imax); cc[1][1]=1; cc[1][2]=c2[imax][2]/c2[imax][1]; cc[1][3]=c2[imax][3]/c2[imax][1];   for(ie=0;ie<=1;ie++){ if(ie !=imax){ c1[0][2]=c2[ie][2]-cc[1][2]*c2[ie][1]; c1[0][3]=c2[ie][3]-cc[1][3]*c2[ie][1]; } } cc[2][2]=1; cc[2][3]=c1[0][3]/c1[0][2]; } /*-----------------------*/ void pivot(int *eli,double c[3][4],int *imax){ int ie; double cmax; if(*eli ==0){ cmax=0; for(ie=0;ie<=2;ie++){ if(fabs(c[ie][0])>cmax){ cmax=c[ie][0]; *imax=ie; } } } else{ cmax=0; for(ie=0;ie<=1;ie++){ if(fabs(c[ie][1])>cmax){ cmax=c[ie][1]; *imax=ie; } } } } /*-----------------------*/ void outputdata(double x[3]){ int i; printf("------\n"); printf("Solutions\n"); for(i=0;i<=2;i++){ printf("x%d=%14.6e\n",i,x[i]); } } /*-----------------------*/ void checksol(double check[3][4],double x[3]){ double crt,clt; int ie,ic; printf("------\n"); printf("Check Solutions\n"); printf("Left Term Right Term\n"); for(ie =0;ie<=2;ie++){ clt =0 ; for(ic=0;ic<=2;ic++){ clt = clt + check[ie][ic]*x[ic]; } crt = check[ie][3]; printf("%14.6e%14.6e\n",clt,crt); } }

みんなの回答

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.3

>関数pivotは,3つの引数を利用しているが,これを2つに減らす方法はないか?  その前に、「関数は、void 型」という拘りがあるのでしょうか。  無い場合、 関数 pivot を、int 型とし、  呼び出し元で、    imax = pivot( 0, c3 );      ・    imax = pivot( 1, c2 ); とするのが普通かな。  関数 pivot は(共通部分を簡略化して)、    int pivot( int eli, double c[][4] )     eli は、int * でない    {      int ie, imax;      double cmax = 0.0;      for( ie = 0; ie <= ( 2 - eli ); ie++ ){        if( fabs( c[ ie ][ eli ] ) > cmax ){          cmax = c[ ie ][ eli ];          imax = ie;        }      }      return( imax );    }

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

なぜ減らしたいんでしょうか?

  • prophetok
  • ベストアンサー率44% (13/29)
回答No.1

構造体で渡せば2つでも1つでも可能。

関連するQ&A

  • 数値解析に関する質問です。

    数値解析に関する質問です。 以下のプログラムでは、4元1次連立方程式のデータは、cとcheckの2つの配列に入力される。この理由を教えてください。また、1つの配列に入力して済ませる方法を教えてください。 よろしくお願いします。 /*kadai 13 Gaussian Elimination Method for System of Linear Equations*/ #include <stdio.h> #include<math.h> /*---------------------------*/ void inputdata(double[4][5],double [4][5]); void calsol(double [4][5],double [4]); void elimination(double [4][5], double [4][5]); void pivot(int *, double [4][5], int *); void outputdata(double [4]); void checksol(double [4][5],double [4]); /*---------------------------*/ main(){ double c[4][5], check[4][5],x[4]; /*---------------------------*/ printf("Program of Gaussian Elimination Method 3\n"); /*---------------------------*/ inputdata(c, check); /*---------------------------*/ calsol(c,x); /*---------------------------*/ outputdata(x); /*---------------------------*/ checksol(check, x); /*---------------------------*/ return(0); } /*---------------------------*/ /* Function inputdata */ /*--------------------------*/ void inputdata(double c[4][5],double check[4][5]){ int ie,ic; printf("-----\n"); printf("Input Data\n"); printf("(a0*x0 + a1*x1 + a2*x2 +a3*x3 = a4)\n"); printf("\n"); for(ie=0; ie<=3; ie++){ printf("Equation %d\n",ie); printf("Input a0 a1 a2 a3 a4\n"); for (ic=0; ic<=4; ic++){ scanf("%lf",&c[ie][ic]); check[ie][ic] = c[ie][ic]; } } } /*---------------------------*/ /* Functiom calsol */ /*---------------------------*/ void calsol(double c[4][5],double x[4]){ double cc[4][5]; elimination(c, cc); x[3]=cc[3][4]; x[2]=cc[2][4]-cc[2][3]*x[3]; x[1]=cc[1][4]-cc[1][3]*x[3]-cc[1][2]*x[2]; x[0]=cc[0][4]-cc[0][3]*x[3]-cc[0][2]*x[2]-cc[0][1]*x[1]; } /*---------------------------*/ /*Function elimination */ /*---------------------------*/ void elimination(double c[4][5],double cc[4][5]){ int ie,ic,ienew,imax,eli; eli = 0; while(eli<4){ pivot(&eli,c,&imax); cc[eli][eli] = 1; for(ie=eli+1;ie<=4;ie++){ cc[eli][ie]=c[imax][ie]/c[imax][eli]; } ienew= 0; for(ic=0;ic<=3-eli;ic++){ if(ie != imax){ for(ie=eli+1;ie<=4;ie++){ c[ienew][ie]=c[ic][ie]-cc[eli][ie]*c[ic][eli]; } ienew = ienew + 1; } } eli = eli +1; } } /*---------------------------*/ /*Function pivot */ /*---------------------------*/ void pivot(int *eli,double c[4][5],int *imax){ int ie; double cmax; cmax=0; for(ie=0;ie<=4-*eli;ie++){ if(fabs(c[ie][*eli])>cmax){ cmax=fabs(c[ie][*eli]); *imax=ie; } } } /*---------------------------*/ /*Function outputdata */ /*---------------------------*/ void outputdata(double x[4]){ int i; printf("------\n"); printf("Solutions\n"); for(i=0;i<=3;i++){ printf("x%d=%14.6e\n",i,x[i]); } } /*---------------------------*/ /*Function checksol*/ /*---------------------------*/ void checksol(double check[4][5],double x[4]){ double crt,clt; int ie,ic; printf("-------\n"); printf("Check Solutions\n"); printf("Left Term Right Term\n"); for(ie=0;ie<=3;ie++){ clt = 0; for(ic =0;ic<=3;ic++){ clt = clt + check[ie][ic]*x[ic]; } crt = check[ie][4]; printf("%14.6e %14.6e\n",clt,crt); } }

  • 数値解析に関する質問です

    以下のプログラムにおいて 1) 初項の絶対値が大きい方の式を選んで消去する理由は何故か? 2)2元1次連立方程式の解が得られないデータ(例えば,1 2 3と2 4 6)を入力した場合,エラーを表示するようにするにはどうすればよいか? 教えてください。 よろしくお願いします。 #include <stdio.h> #include<math.h> //-------------------------------- void inputdata(double [2][3]); void calsol(double [2][3], double [2]); void elimination(double [2][3], double [2][3]); void outputdata(double [2]); void checksol(double [2][3], double [2]); //--------------------------------- main() { double c[2][3], x[2]; printf("Program of Gaussian elimination \n"); inputdata(c); calsol(c, x); outputdata(x); checksol(c, x); return(0); } //----------------------------- void inputdata(double c[2][3]) { printf("----------------------\n"); printf("Input Data\n"); printf("(a0*x0 + a1*x1 = a2)\n"); printf("\n"); printf("Equation 1\n"); printf("Input a0 a1 a2\n"); scanf("%lf%lf%lf" , &c[0][0], &c[0][1], &c[0][2]); printf("Equation 2\n"); printf("Input b0 b1 b2\n"); scanf("%lf%lf%lf", &c[1][0], &c[1][1], &c[1][2]); } //----------------------------- void calsol(double c[2][3], double x[2]){ double cc[2][3]; elimination(c, cc); x[1]=cc[1][2]; x[0]=cc[0][2]-cc[0][1]*x[1]; } //----------------------------- void elimination(double c2[2][3],double cc[2][3]) { int imax; double c1[3]; if(fabs(c2[0][0])>fabs(c2[1][0])){ imax = 0; } else{ imax = 1; } cc[0][0] = 1; if (imax == 0){ cc[0][1]= c2[imax][1]/c2[imax][0]; cc[0][2]=c2[imax][2]/c2[imax][0]; } else{ cc[0][1]=c2[1][1]/c2[1][0]; cc[0][2]=c2[1][2]/c2[1][0]; c1[0]=0; c1[1]=c2[0][1]-(cc[0][1]*c2[0][0]); c1[2]=c2[0][2]-(cc[0][2]*c2[0][0]); } cc[1][0]=c1[0]; cc[1][1]=1; cc[1][2]=c1[2]/c1[1]; } //----------------------------- void outputdata(double x[2]){ printf("--------\n"); printf("Solutions\n"); printf("x0=%14.6e\n", x[0]); printf("x1=%14.6e\n", x[1]); } //----------------------------- void checksol(double check [2][3],double x[2]) { double crt, clt; int ie; printf("---------\n"); printf("Check Solutions\n"); printf("Left Term Right Term\n"); for(ie=0; ie<=1; ie++) { clt = check[ie][0]*x[0] + check[ie][1]*x[1]; crt = check[ie][2]; printf("%14.6e %14.6e\n", clt,crt); } } 実行結果 Program of Gaussian elimination ---------------------- Input Data (a0*x0 + a1*x1 = a2) Equation 1 Input a0 a1 a2 2 3 13 Equation 2 Input b0 b1 b2 4 8 32 -------- Solutions x0= 2.000000e+00 x1= 3.000000e+00 --------- Check Solutions Left Term Right Term 1.300000e+01 1.300000e+01 3.200000e+01 3.200000e+01

  • 数値解析に関する質問です。

    /*kadai8 Euler’s Method for Ordinary Differential Equation */ #include <stdio.h> void euler(double *, double *); main () { int i; double v,t,tt,dt[5]; dt[0] = 2; dt[1] = 1; dt[2] = 0.1; dt[3] = 0.01; dt[4] = 0.001; printf("Program of Euler`s Method 1\n"); printf("-----------------------------------------\n"); tt = 50.0/9.80665; printf("Theoretical Solution : %lfs\n",tt); for(i=0;i<=4;i++){ printf("--------------------------------\n"); printf("Step Size : %lf s\n",dt[i]); v=50.0; t=0.0; while(v>0) { euler(&v,&dt[i]); t=t+dt[i]; } printf("Numerical Solution : %lf s\n",t); printf("Error : %lf s\n",t-tt); } return(0); } /*--------------*/ void euler(double *v,double *dt) { *v=*v + (*dt )*(-9.80665); } 以上のプログラムで関数eulerの引数にポインタがついているのはなぜか,またポインタを使用しない方法はないか?また、オイラー法より精度の高い解法はありますか? よろしくお願いします。

  • 数値解析法

    このHeun法のプログラムをRunge-Kutta法にするにはどうしたらいいですか? #include <stdio.h> #include <math.h> double f1(double y) { return y; } double f2(double y) { return -4*y; } int main(){ double a=0; double b; int m=10; int n; double h; double x,y; int k; double e; double f; double k1,k2; printf("Heun法計算例:y=e^x, y=1/e^4x\n\n"); // y = e^x b = 1; for(n=100;n<=10000;n*=100){ h = (b-a)/n; printf("y' = y: h(=dx) = %.1e (y=e^x)\n",h); x = a; y = 1; for(k=0;k<=n;k++) { x = k*h; if(k%(n/m)==0) { f = exp(x); e = fabs(y-f); printf("x=%.2f, y=%f, e^x=%f er=%.0e\n",x,y,f,e); } // Heun's method k1 = h*f1(y); k2 = h*f1(y+k1); y += (k1+k2)/2; } }

  • 配列要素内の数値

    #include <stdio.h> int main(void) { int arr[1]={123456789}; int *x[1]; *x = arr; printf("%d ",*(x[0])); /* 123456789 と表示*/ return 0;} 実行すると123456789と表示されるまでは分かるのですが、*(x[0])の部分を別の書き方にして、arr[0]に入ってある「123456789」という数値の千の値である6という数値のみを取り出して、表示することは可能なのでしょうか?(6000と取り出したいのではなく、6として取り出したい) 次のように数値を文字列の一つ一つを扱うかのように、扱いたいのです。*(x[0])の部分の変更だけで6を取り出せるような方法はありますか? #include <stdio.h> int main(void) { char *arr[]={"pen"}; printf("%c\n",*(arr[0]+0)); printf("%c\n",*(arr[0]+1)); printf("%c\n",*(arr[0]+2)); return 0;}

  • C++についての質問です

    プログラミング初心者です 以下の通りに正方行列の積を求めるプログラムを作成したのですが、うまくいきません。 #include<stdio.h> #define DTM 20 void InputMatrix(double[][DTM], int, char); void PrintMatrix(double[][DTM], int, char); void MatrixMulti(double[][DTM], double[][DTM], double[][DTM], int); int main(void) { double matrixA[DTM][DTM]; double matrixB[DTM][DTM]; double matrixC[DTM][DTM]; int n; printf("正方行列の積を求めるプログラムです\n"); printf("正方行列の次元を入れてください(<=20):"); scanf_s("%d", &n); InputMatrix(matrixA, n, 'A'); InputMatrix(matrixB, n, 'B'); MatrixMulti(matrixA, matrixB, matrixC, n); printf("\n行列 C =A×B\n"); PrintMatrix(matrixC, n, 'C'); return 0; } void InputMatrix(double a[][DTM], int n, char ch) { int i, j; printf("行列 %cの入力\n", ch); for (i = 0; i < n;i++) { for (j = 0;j < n;j++) { printf("%c[%d][%d] =", ch, i + 1, j + 1); scanf_s("%lf", &a[i][j]); } } } void PrintMatrix(double a[][DTM], int n, char ch) { int i, j; printf("行列 %c の出力\n", ch); for (i = 0;i < n;i++) { for (j = 0;j < n;j++) { printf("%5.2f\t", a[i][j]); } printf("\n"); } } void MatrixMulti(double a[][DTM], double b[][DTM], double c[][DTM], int n) { int i, j, k; for (i = 0;i < n;i++) { for (j = 0;j < n;j++) { c[i][j] = 0; for (k = 0;k < n;k++) { c[i][j] =a[i][k] * b[k][j]; } printf("%5.2f\t",c[i][j]); } printf("\n"); } }

  • C言語課題(数値計算)お願いします。

    課題内容 ニュートン法を用いて√2の値を求められるプログラムを作る。 10ケタまで表示する。 書いてみたソースコード #include <stdio.h> #include <stdlib.h> #include <math.h> #define max 1000 //最大繰り返し回数 #define eps 1.0e-10 //収束条件 double f(double x); double df(double x); void newton(void); int main() { newton(); return 0; } void newton(void) { int count; double a,newa; count=0; printf("初期値を入力してください。\n"); scanf("%lf",&a); for(;;) { count++; newa=a-f(a)/df(a); if(fabs(newa-a)<eps) break; a=newa; if(count==max) { printf("収束しませんでした。\n"); exit(1); } } printf("解の値は %f\n収束するのに %d 回かかりました。\n", newa,count); } double f(double x) { return x*x-2; } double df(double x) { return 2x; } コンパイルできません。 間違いとどうすればよいかを教えていただけるとありがたいです!!!

  • C言語について質問です。

    前に質問した訂正です。前の質問に関しては質問の意図が伝わりにくい文章で本当に申し訳ないと思っています。 乱数列の要素数Nの値を変えていきバブルソートの交換回数、比較回数を数えるプログラムを作り、後は処理時間について調べたいのですが、処理時間を出力させることはできたんですが、単位がわかりません。教えてください。 以下に乱数を生成するrand.cとバブルソートを行うbubblesort.cを記載します。 rand.c #include <stdio.h> #include <stdlib.h> #include <time.h> #define N 1000 int num[N]; int makeDataFile ( void ) { int i; FILE *fp; char s[100]; int num[N]; srand ( ( unsigned )time ( NULL ) ); fp = fopen ("rand1.txt", "w" ); if ( fp == NULL ) exit(1); for ( i = 0; i < N; i++ ){ fprintf ( fp, "%d\n", rand()%100 ); } fclose ( fp ); fp = fopen ( "rand1.txt", "r" ); if ( fp == NULL ) exit(1); while( fgets ( s, sizeof (s), fp ) ) { printf ( s ); } fclose ( fp ); return N; } bubblesort.c #include <stdio.h> #include <time.h> extern int makeDataFile ( void ); extern int num[]; void BubbleSort ( int x[] , int n ); void Show ( int x[] , int n ); int comp; int swap; void BubbleSort ( int x[] , int n ) { int i, j, tmp; for ( i = 0; i < n-1; i++ ) { for ( j = n-1; j > i; j-- ){ comp++; if ( x[i] > x[j] ){ swap++; tmp = x[j]; x[j] = x[i]; x[i]= tmp; Show ( x , n ); } } } } void Show ( int x[] , int n ) { while ( n-- ) printf ( "%d " , *x++ ); printf ( "\n" ); } int main(void) { int i, j, n , tmp; FILE *fp; comp = 0; swap = 0; n = makeDataFile(); clock_t start , finish; double duration; start = clock(); fp = fopen ( "rand1.txt", "r" ); if ( fp == NULL ) return 1; for ( i = 0; i < n; i++ ){ fscanf ( fp, "%d", &(num[i] ) ); } fclose ( fp ); printf ( "\nbefore bubblesort\n" ); Show ( num , n ); printf ( "\n" ); printf ( "progress bubblesort\n" ); BubbleSort ( num , n ); printf ( "\n" ); printf ( "after bubblesort\n" ); Show ( num , n ); printf ( "\n" ); finish = clock(); duration = (double)(finish-start) / CLOCKS_PER_SEC; printf ( "count of comparisons : %d\n" , comp ); printf ( "count of swap : %d\n" , swap ); printf ( "%lf\n" , duration ); return 0; } 実行結果: >gcc rand.c bubblesort.c (ソートは省略) count of comparisons : 499500 count of swap : 14848 2.950000 と出力されたのですが読み方?単位が分かりません。教えてください。自分の答えとしては2分55秒だと思うんですが合ってますか?連続質問ですいません。

  • 引数に二重配列のある関数について

    void calc(int *a,int b,int c){ a[0]=b+c; a[1]=b-c; } void main(void){ int x[2]; int y=2,z=5; calc(x,y,z); printf("x[0]=%d,x[1]=%d\n",x[0],x[1]); } 上のように引数が普通の配列の関数ならできるのですが, 引数が下のような多重配列になるとエラーが出てしまいできません。 void keisan(int **a,int b,int c){ a[0][0]=b+c; a[0][1]=b-c; a[1][0]=b*c; a[1][1]=b/c; } void main(void){ int x[2][2]; keisan(x,6,2); printf("x[0][0]=%d,x[0][1]=%d\n",x[0][0],x[0][1]); printf("x[1][0]=%d,x[1][1]=%d\n",x[1][0],x[1][1]); } 引数に多重配列を使った場合の関数の作り方について教えてください. お願いいたします.

  • voidについて

    いつもお世話になってます。 最近プログラミングの授業に全然ついていけなくて、1から勉強しようと思ってます。 今回はvoidについて質問なのですが、たとえば下のようなプログラムがあるとします(あえてabcとcdfとxyzを使い分けています。) 数字を入力するとプロトタイプ宣言した関数で足して戻り値が答え(←日本語あってますか?)ってことですよね? 私はvoid関数についてあまり理解できていないので、void関数ではどのように数字が動いているかとどれを一致させなければいけないのかをabcdefxyzを使って詳しく解説していただきたいです。 あと関数の起動の仕方(←日本語あってますか?)も教えていただきたいです。      c=tasu(a,b); printf("%lg\n",c);という方法とか      tasu(a,b); ←これだけとか )   文章ぐだぐだで申し訳ないです。 どなたかおねがいいたします。   ) #include<stdio.h> void tasu(double x, double y, double z); int main(void){ double a,b,c;      printf("1つ目の数字を入力>"); scanf("%lg", &a); printf("2つ目の数字を入力>"); scanf("%lg", &b); c=tasu(a,b); printf("%lg\n",c); return 0; } void tasu(int x, int y, int z) { d = e + f; }