質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

3回答

3198閲覧

C言語で逆行列の実装をしたいです。

kinjouhiro

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2021/05/10 17:34

前提・実現したいこと

C言語です。授業の課題なのですが逆行列が求まりません。
以下の行列に対し,逆行列A-1を求めるためのプログラムを作成しなさい.
ただし,“K”には標準入力から,0~3の数字をそれぞれ入れて実行しなさい.
3 8 -2 6
-3 2 K 5
6 -4 -4 -10
1 1.5 -3 7

ただし、逆行列を求めるさいに、逆行列が存在するかどうかの判定を組み込みたいです。

発生している問題・エラーメッセージ

c:70:14: warning: passing argument 2 of 'pivot' from incompatible pointer type [-Wincompatible-pointer-types] pivot(a,c,i); ^ c:7:6: note: expected 'double *' but argument is of type 'double (*)[4]' void pivot(double a[][N],double b[N],int p); ただ、このエラーが出ていてもプログラム時代は動きます。 そのかわり、0~3度の値を入れても逆行列はないと返されます。

該当のソースコード

C言語

1#include <stdio.h> 2#include <stdlib.h> /* malloc関数を使用するのに必要 */ 3#include <string.h> 4#define EPSIRON 0.0005 // 丸め誤差対策 5#define N 4 6 7void pivot(double a[][N],double b[N],int p);/* ピボット処理用関数の定義 */ 8 9int main(void){ 10 double a[N][N], b[N] ,c[N][N] ,temp; 11 double K; 12 int i, j, k, n; 13 char file; 14 int count; /* すべての変数を使うかどうかはわかりません */ 15 char file_name[20]="ginverse.txt"; /* ファイル名の読み取り用 */ 16 char str[16]; 17 FILE *fp; 18 /* ファイル名の入力・ファイルからデータの取得 */ 19 printf("enter file name:"); 20 //scanf("%s",file_name); 21 fp = fopen(file_name, "r"); // ファイルを開く。失敗するとNULLを返す。 22 if(fp == NULL) { 23 printf("%s file not open!\n", file_name); 24 return -1; 25 } 26 27 for( i = 0; i < N; i++ ) { 28 for(j=0;j < N; j++){ 29 fscanf(fp, "%lf", &a[i][j]); 30 } 31 } 32 printf("Enter K number(0~3):"); 33 scanf("%d",&K); 34 if(K>3||K<0){ 35 printf("please Enter between 0 to 3"); 36 }else{ 37 a[1][2] = K; 38 printf("a[1][2]=%d",K); 39 } 40 41 for(i=0;i<N;i++){ 42 /* ピボット操作が必要かどうかの確認 */ 43 /* 必要ならばピボット操作のための関数へ */ 44 if(a[i][i]<=EPSIRON){ 45 pivot(a,b,i); 46 } 47 for(j=0;j<N;j++){ 48 if(j==i){ 49 a[i][j] = a[i][j]/a[i][i]; 50 }else 51 for(k=0;k<N;k++){ 52 a[k][j] = a[k][j]-a[i][j]*a[k][i]; 53 } 54 } 55 56 if(a[N][N]=!0){//ランクが落ちたことを判定 57 printf("\nNo Inverse Matrix"); 58 }else if(i==N){ 59 for( i = 0; i < N; i++ ) { 60 for(j=0;j < N; j++){ 61 fscanf(fp, "%lf", &a[i][j]); 62 if(i==j){ 63 c[i][j]=1; 64 }else{ 65 c[i][j]=0; 66 } 67 68 } 69 } 70 a[1][2]=K; 71 pivot(a,c,i); 72 73} 74 75 76 } 77 78 return 0; 79} 80 81 82void pivot(double a[][N], double b[N], int p){ 83 /* pivot変換用関数 */ 84 int i,pivot; 85 double max_value; /* 最大の変数を格納 */ 86 double temp_value; 87 double temp[N]; 88 89max_value = 0; /* 必要な変数の初期化 */ 90 pivot = 0; 91 /* どの係数a[i][p]が一番大きいかを確認 */ 92 printf("\npは%dです。\n",p); 93 temp_value = a[p][p]; 94 for(i=0;i<N;i++){ 95 96 if (temp_value < a[i][p]){ 97 pivot = i; 98 temp_value=a[i][p]; 99 printf("pivotに%dが代入されました、",pivot); 100 //printf("よってa[%d][%d]は%lfです\n",p,p,a[p][p]); 101 }else printf("%dではpivot操作はおこなわれませんでした\n",i); 102 103 } 104 /* 一番大きい係数だった行と入れ替える */ 105 for(i=0;i<N;i++) 106 { 107 printf("pivotに%dが、iに%dが代入されています,",pivot,i); 108 temp[i]=a[p][i]; 109 a[p][i]=a[pivot][i]; 110 a[pivot][i]=temp[i]; 111 /*printf("temp[%d] = %lf,",i,temp[i]); 112 printf("a[%d][%d] = %lf, ", p, i, a[p][i]); 113 printf("a[%d][%d] = %lf\n ", pivot, i, a[pivot][i]); 114 /* この中でaの行の値を各列ごとに入れ替える */ 115 } 116 117 /* bの行の値も入れ替えるのを忘れずに 118 temp[p]=b[p]; 119 b[p]=b[pivot]; 120 b[pivot]=temp[p];*/ 121 //printf("b[%d] = %lf, ",p, b[pivot]); 122 /*for(i=0;i<N;i++){ 123 for(p=0;p<=N;p++){ 124 if(p==N){ 125 printf("b[%d] = %lf\n", i,b[i]); 126 } 127 else{ 128 printf("a[%d][%d] = %lf, ", i, p, a[i][p]); 129 } 130 } 131 }*/ 132}

試したこと

何か所かにprintfでどう値が代入されているかを確認しています。

補足情報(FW/ツールのバージョンなど)

VScodeです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

とりあえず警告について、関数pivotに渡す変数の型が違うと怒られてますね
pivot(a,c,i) は、渡している変数の型に着目すると
pivot(double[N][N], double[N][N], int)
ですが、実装されている関数pivotの定義は
void pivot(double[][N],double[N],int)

で、2番目の引数の型が違うのがわかりますね。渡す変数を間違えているか、関数の実装を間違えているのではないでしょうか

~~~~~~~~~~~
余談ですが、関数pivotの中に変数pivotが存在するとちょっと混乱しちゃうので、できれば別の名前にした方が読みやすいと思いますよ。関数pivotを検索した時に変数まで引っかかったりするので。
せめて大文字小文字で変えるとか(関数の頭は大文字、変数の頭は小文字とか)した方が良いかと。

投稿2021/05/11 00:58

編集2021/05/11 11:53
WoodenHamlet

総合スコア306

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

WoodenHamletさんが書かれているように、ワーニングの原因はプロトタイプ宣言と関数呼び出しの不整合です。
これは、連立一次方程式の解法のコードを逆行列に転用しようとしてちゃんと書き直していないことが原因でしょう。

行列と、その逆行列を別々の領域に取るより拡大行列にしたほうが処理はわかりやすくなります。

掃き出し法(ガウスの消去法)による連立方程式の解法と逆行列の求め方あたりをよく読んで、ちゃんとコーディングしなおすことをお勧めします。

投稿2021/05/11 03:52

ppaul

総合スコア24666

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

× if(a[N][N]**=!0){//ランクが落ちたことを判定
○ if(a[N][N]
!=**0){//ランクが落ちたことを判定

※ ただし、「a[N][N] が 0 でないとき、逆行列は存在しない」なら。

投稿2021/05/10 20:58

編集2021/05/10 21:01
episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問