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

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

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

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

3034閲覧

過程の計算処理を表示させたい。

carnage0216

総合スコア194

C

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/07/19 18:44

環境

  • windows10
  • visual studio 2017
/********************************************* * 連立方程式の解法 ( ガウスの消去法 ) *********************************************/ #include <iostream> // for cout #include <stdio.h> // for printf() // 元の数定義 #define N 4 // 3 using namespace std; /* * 計算クラス */ class Calc { double a[N][N + 1]; // 各種変数 double d; // ダミー int i, j, k; // LOOP インデックス public: // 連立方程式を解く(ガウスの消去法) void calcGaussElimination(); }; /* * 連立方程式を解く(ガウスの消去法) */ void Calc::calcGaussElimination() { // 係数 static double a[N][N + 1] = { //{ 2.0, -3.0, 1.0, 5.0}, //{ 1.0, 1.0, -1.0, 2.0}, //{ 3.0, 5.0, -7.0, 0.0} { 1.0, -2.0, 3.0, -4.0, 5.0}, {-2.0, 5.0, 8.0, -3.0, 9.0}, { 5.0, 4.0, 7.0, 1.0, -1.0}, { 9.0, 7.0, 3.0, 5.0, 4.0} }; // 元の連立方程式をコンソール出力 for (i = 0; i < N; i++) { for (j = 0; j < N; j++) printf("%+fx%d ", a[i][j], j + 1); printf("= %+f\n", a[i][N]); } // 前進消去 for (k = 0; k < N -1; k++) { for (i = k + 1; i < N; i++) { d = a[i][k] / a[k][k]; for (j = k + 1; j <= N; j++) a[i][j] -= a[k][j] * d; } } // 後退代入 for (i = N - 1; i >= 0; i--) { d = a[i][N]; for (j = i + 1; j < N; j++) d -= a[i][j] * a[j][N]; a[i][N] = d / a[i][i]; } // 結果出力 for (k = 0; k < N; k++) printf("x%d = %f\n", k + 1, a[k][N]); } /* * メイン処理 */ int main() { try { // 計算クラスインスタンス化 Calc objCalc; // 連立方程式を解く(ガウスの消去法) objCalc.calcGaussElimination(); } catch (...) { cout << "例外発生!" << endl; return -1; } // 正常終了 return 0; }

の以下の

// 前進消去 for (k = 0; k < N -1; k++) { for (i = k + 1; i < N; i++) { d = a[i][k] / a[k][k]; for (j = k + 1; j <= N; j++) a[i][j] -= a[k][j] * d; } }

の部分において過程の計算処理が見たかったのでprintf関数を使ったのですが警告がでます。
変数の型を考慮しながら以下のように書きました。

// 前進消去 for (k = 0; k < N - 1; k++) { for (i = k + 1; i < N; i++) { d = a[i][k] / a[k][k]; for (j = k + 1; j <= N; j++) a[i][j] -= a[k][j] * d; //a[i][j] = a[i][j]-a[k][j] * d printf("a=%lf\nである", a);//付け加えた部分~~ printf("%d=a[%d][%d] /a[%d][%d]\n ", a,i,k,k,k); printf("[k]=%d\n", k); printf("a[%d][%d]=a[%d][%d]-a[%d][%d]*%lf\n", i, j, i, j, k, j, d);//~~ここまで付け加えました。 } }

以下が警告です。

1>------ ビルド開始: プロジェクト: サイトに載っていた連立方程式の計算, 構成: Release x64 ------ 1>Source.cpp 1>c:\users\daito\source\repos\サイトに載っていた連立方程式の計算\サイトに載っていた連立方程式の計算\source.cpp(58): warning C4477: 'printf' : 書式文字列 '%lf' には、型 'double' の引数が必要ですが、可変個引数 1 は型 'double (*)[5]' です 1>c:\users\daito\source\repos\サイトに載っていた連立方程式の計算\サイトに載っていた連立方程式の計算\source.cpp(59): warning C4477: 'printf' : 書式文字列 '%d' には、型 'int' の引数が必要ですが、可変個引数 1 は型 'double (*)[5]' です 1>c:\users\daito\source\repos\サイトに載っていた連立方程式の計算\サイトに載っていた連立方程式の計算\source.cpp(59): warning C4313: 'printf': 書式文字列内の '%d' が引数 1 ('double (*)[5]' 型) と競合しています。 1>コード生成しています。 1>0 of 16 functions ( 0.0%) were compiled, the rest were copied from previous compilation. 1> 0 functions were new in current compilation 1> 0 functions had inline decision re-evaluated but remain unchanged 1>コード生成が終了しました。 1>サイトに載っていた連立方程式の計算.vcxproj -> c:\users\daito\source\repos\サイトに載っていた連立方程式の計算\x64\Release\サイトに載っていた連立方程式の計算.exe 1>プロジェクト "サイトに載っていた連立方程式の計算.vcxproj" のビルドが終了しました。 ========== ビルド: 1 正常終了、0 失敗、0 更新不要、0 スキップ ==========

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

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

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

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

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

guest

回答4

0

ベストアンサー

c

1for (k = 0; k < N - 1; k++) { 2 for (i = k + 1; i < N; i++) { 3 d = a[i][k] / a[k][k]; 4 for (j = k + 1; j <= N; j++) 5 a[i][j] -= a[k][j] * d; //a[i][j] = a[i][j]-a[k][j] * d 6 7 printf("a=%lf\nである", a);//付け加えた部分~~ 8 // ^ (1) 9 printf("%d=a[%d][%d] /a[%d][%d]\n ", a,i,k,k,k); 10 // ^^ ^ (2) 11 printf("[k]=%d\n", k); 12 printf("a[%d][%d]=a[%d][%d]-a[%d][%d]*%lf\n", i, j, i, j, k, j, d);//~~ここまで付け加えました。 13 } 14}

こちらですが、上でコメントした 2 個所に問題があります。

(1) a は二次元配列なので printf() では表示できない。

前の回答者さんが指摘されている通りです。
ここ、本当は a を全部表示したいのではなく a[i][j] を表示したいのではありませんか。

(2) a は二次元配列なので printf() では表示できない。

ここ、本当は a ではなく d を表示したいのではありませんか。ちなみに d は double なのですが、 %d でよいですか。
クラス内の宣言で d がダミーとコメントされているのが気になりますが、 d は重要な役割を果たしているはず...。

まずはエラーや警告を読んでみるところから

前の回答者さんもおっしゃっていますが、警告は読まれましたか。たとえばこれ。

書式文字列 '%lf' には、型 'double' の引数が必要ですが、可変個引数 1 は型 'double (*)[5]' です

とても親切な警告文だと思います。これを見ると %lf に対して二次元配列を渡していることが一目で分かります。たとえ double (*)[5] が初めなんのことやら分からなかったとしても、 指摘されている行数を見る%lf で表示されるべき場所に a を渡していることが分かりますよね。では a はなんだったかと考えると、二次元配列です。
そこで自分が本当は何をやりたかったのかもう一度考えてください。二次元配列の中身を全て表示したかったのなら、 for ループを書くことになるでしょう。特定の一つの要素を表示したくて添字を付け忘れているのなら、添字を追加してください。

エラーや警告は初心者のうちは「どうせ読んでも分からない」と考えがちなのかもしれません。確かに、 (特に C++ は) コンパイラが複雑怪奇なエラーを出すこともあります。でも、どれだけ分からないエラーが出ても、必ずそこには エラーや警告が起きた行数が書かれています から、一度は自分の書いたコードのその行を見直してください。エラーが 言っていることが分からなくても、間違いを直す方法は分かる 、ということは多々あります。

どうかエラーや警告を読むことを諦めないでくださいね。 どんなに難解でも、少なくとも指摘された行は見直す 、です。

ちなみに、それでもどうしても直し方が分からない場合は質問して大丈夫ですよ。そういうときのための teratail ですからね。自分がエラーや警告を読んで考えたことも質問に盛り込めば、回答者さんも「ちゃんと考えてから聞いているんだな」という印象になって、気持ち良く回答してくださると思いますよ。

(補足)

エラーや警告は、前のエラーにひきずられてどばーーーーーっと出ることがあります。大量のエラーが出ても一歩も引かないでくださいね。まずは一番最初のエラーを見てみましょう。たいてい最初のエラーは本物なので、そのエラーを直して再度コンパイルするとがばっとエラーが消えたりします。

あまり大規模なものだと毎回再コンパイルするわけにはいかないかもしれませんが、練習程度の小さい規模のものなら、一番最初のエラーをつぶしたらとりあえず再コンパイルしてみるとよいでしょう。

直すとエラーが増えるパターンというのもありますが、同じところに同じエラーが出ていないなら、それは確実に一歩進んでいます。諦めないで、また一番最初のエラーから読んでいきましょう。

応援していますので、少しずつやってみてくださいね。

投稿2018/07/20 03:39

編集2018/07/20 03:45
Eki

総合スコア429

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

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

carnage0216

2018/07/20 14:13

親切に回答して頂き本当にありがとうございます。 じっくり読ませてエラー、警告を解決していきます。
guest

0

おフザケついでに CUDA(cuSOLVER)で解いてみた。
この程度ではちっとも速くないけど。

C++

1// cusolver.cpp 2/* how to compile : */ 3 set CUDA_DIR="C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.2" 4 set CUDA_INC=%CUDA_DIR%/include 5 set CUDA_LIB=%CUDA_DIR%/lib/x64 6 cl -EHsc -I%CUDA_INC% -wd4819 cusolver.cpp cudart.lib cusolver.lib -link -libpath:%CUDA_LIB% 7*/ 8 9#include <cuda_runtime.h> 10#include <cusolverDn.h> // dense LAPACK 11 12#include <cassert> 13#include <iostream> 14using namespace std; 15 16template<typename T> 17inline size_t bytesof(unsigned int s) { return s * sizeof(T); } 18 19template<typename T> 20T* allocate(unsigned int size) { 21 T* result = nullptr; 22 cudaError_t status = cudaMalloc(&result, bytesof<T>(size)); 23 assert( status == cudaSuccess ); 24 return result; 25} 26 27int main() { 28 cusolverStatus_t status; 29 30 // dense LAPACK 31 cusolverDnHandle_t handle; 32 status = cusolverDnCreate(&handle); 33 assert( status == CUSOLVER_STATUS_SUCCESS ); 34 35 const int n = 4; 36 37 float A[n][n] = { 38 { 1.0, -2.0, 3.0, -4.0 }, 39 {-2.0, 5.0, 8.0, -3.0 }, 40 { 5.0, 4.0, 7.0, 1.0 }, 41 { 9.0, 7.0, 3.0, 5.0 } 42 }; 43 float* dA = allocate<float>(n*n); 44 cudaMemcpy(dA, A, bytesof<float>(n*n), cudaMemcpyHostToDevice); 45 int lda = 4; 46 47 // 必要なバッファ量を求め、確保する 48 int worksize; 49 status = cusolverDnSgetrf_bufferSize( 50 handle, 51 n, // 行 52 n, // 列 53 dA, // A 54 lda, // Aのヨコハバ 55 &worksize); 56 assert( status == CUSOLVER_STATUS_SUCCESS ); 57#ifdef _DEBUG 58 cout << "worksize = " << worksize << endl; 59#endif 60 61 float* workspace = allocate<float>(worksize); 62 63 // 計算結果に関する情報 64 int* devInfo = allocate<int>(1); 65 // ピボット 66 int* pivot = allocate<int>(n); 67 68 // LU分解 : dAに結果が求まる(それとpivot) 69 status = cusolverDnSgetrf( 70 handle, 71 n, // 行 72 n, // 列 73 dA, // A 74 lda, // Aのヨコハバ 75 workspace, 76 pivot, 77 devInfo); 78#ifdef _DEBUG 79 int info; 80 cudaMemcpy(&info, devInfo, sizeof(int), cudaMemcpyDeviceToHost); 81 cout << "info = " << info << endl; 82#endif 83 assert( status == CUSOLVER_STATUS_SUCCESS ); 84 85 float B[] = { 5.0, 9.0, -1.0, 4.0 }; 86 int nrhs = 1; // 問題数 87 float* dB = allocate<float>(n*nrhs); 88 cudaMemcpy(dB, B, bytesof<float>(n*nrhs), cudaMemcpyHostToDevice); 89 int ldb = 4; 90 91 // AX = B を解く (解XはBをoverrideする) 92 status = cusolverDnSgetrs( 93 handle, 94 CUBLAS_OP_T, 95 n, // 行(=列) 96 nrhs, // 問題数 97 dA, // A 98 lda, // Aのヨコハバ 99 pivot, // LU分解で得られたピボット 100 dB, // B 101 ldb, // Bのヨコハバ 102 devInfo); 103#ifdef _DEBUG 104 cudaMemcpy(&info, devInfo, sizeof(int), cudaMemcpyDeviceToHost); 105 cout << "info = " << info << endl; 106#endif 107 assert( status == CUSOLVER_STATUS_SUCCESS ); 108 109 // 結果を取得し、出力する 110 cudaMemcpy(B, dB, bytesof<float>(n*nrhs), cudaMemcpyDeviceToHost); 111 for ( int i = 0; i < n; ++i ) { 112 cout << "x" << i+1 << " = " << B[i] << endl; 113 } 114 115 cudaFree(workspace); 116 cudaFree(dA); 117 cudaFree(dB); 118 cudaFree(devInfo); 119 cudaFree(pivot); 120 121 cusolverDnDestroy(handle); 122}

投稿2018/07/21 04:02

episteme

総合スコア16614

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

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

carnage0216

2018/07/22 08:08

なんかここまでして頂いて本当にどうもありがとうございます。 ただ連立方程式の計算過程はパターン化しているのでGPUでのほうが早いと思ったのですが、もしかしたら計算以外の部分で時間を食ってしまいCPUと同等あるいは遅い結果になったのでしょうね。
carnage0216

2018/07/22 09:15

正直に言いますと何をやっているのかはわかっているのですが、なんでこのように書けるのか頭が全く追いつきません。 ただただGPUをここまで使いこなせるのが羨ましい、凄いという感情だけが起きました。
guest

0

解決したのでおマケ。classの体裁を整えた(+pivot操作を追加)。

C++

1/********************************************* 2 * 連立方程式の解法 ( ガウスの消去法 ) 3 *********************************************/ 4#include <cstdio> // printf() 5#include <cmath> // fabs() 6 7#define PIVOT 1 8 9/* 10 * 計算クラス 11 */ 12template<size_t N> 13class Calc { 14 double a[N][N + 1]; 15 16public: 17 Calc(double c[N][N]); 18 // ax = b を解く 19 // 解xはb[N]に上書きする。 20 bool calcGaussElimination(double b[N]); 21}; 22 23template<size_t N> 24Calc<N>::Calc(double c[N][N]) { 25 for ( int i = 0; i < N; ++i ) { 26 for ( int j = 0; j < N; ++j ) { 27 a[i][j] = c[i][j]; 28 } 29 } 30} 31 32/* 33 * 連立方程式を解く(ガウスの消去法) 34 */ 35template<size_t N> 36bool Calc<N>::calcGaussElimination(double b[N]) { 37 for ( int i = 0; i < N; ++i ) { a[i][N] = b[i]; } 38 39 // 前進消去 40 for ( int k = 0; k < N -1; k++ ) { 41#if PIVOT 42 double maxval = fabs(a[k][k]); 43 int maxidx = k; 44 for ( int i = k+1; i < N; ++i ) { 45 if ( maxval < fabs(a[i][k]) ) { 46 maxval = fabs(a[i][k]); 47 maxidx = i; 48 } 49 } 50 if ( maxval == 0.0 ) return false; 51 if ( maxidx != k ) { 52 for ( int i = 0; i <= N; ++i ) { 53 double t = a[maxidx][i]; 54 a[maxidx][i] = a[k][i]; 55 a[k][i] = t; 56 } 57 } 58#endif 59 for ( int i = k + 1; i < N; i++ ) { 60 if ( a[k][k] == 0 ) { 61 return false; 62 } 63 double d = a[i][k] / a[k][k]; 64 for (int j = k + 1; j <= N; j++ ) 65 a[i][j] -= a[k][j] * d; 66 } 67 } 68 69 // 後退代入 70 for ( int i = N - 1; i >= 0; i-- ) { 71 if ( a[i][i] == 0 ) return false; 72 double d = a[i][N]; 73 for (int j = i + 1; j < N; j++) { 74 d -= a[i][j] * a[j][N]; 75 } 76 a[i][N] = d / a[i][i]; 77 } 78 79 // 結果出力 80 for (int k = 0; k < N; k++) 81 b[k] = a[k][N]; 82 83 return true; 84} 85 86/* 87 * メイン処理 88 */ 89int main() { 90 91 const size_t N = 4; 92 93 // 係数 94 double a[N][N] = { 95 { 1.0, -2.0, 3.0, -4.0 }, 96 {-2.0, 5.0, 8.0, -3.0 }, 97 { 5.0, 4.0, 7.0, 1.0 }, 98 { 9.0, 7.0, 3.0, 5.0 } 99 }; 100 double b[N] = { 5.0, 9.0, -1.0, 4.0 }; 101 102 // 元の連立方程式をコンソール出力 103 for (int i = 0; i < N; i++) { 104 for (int j = 0; j < N; j++) { 105 printf("%+fx%d ", a[i][j], j + 1); 106 } 107 printf("= %+f\n", b[i]); 108 } 109 printf("\n"); 110 111 // 計算クラスインスタンス化 112 Calc<N> objCalc(a); 113 114 // 連立方程式を解く(ガウスの消去法) 115 if ( objCalc.calcGaussElimination(b) ) { 116 for (int k = 0; k < N; k++) { 117 printf("x%d = %f\n", k + 1, b[k]); 118 } 119 } 120 121}

投稿2018/07/20 22:23

episteme

総合スコア16614

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

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

0

二次元配列のaに対して
printf("a=%lf\nである", a)
で出力されるわけないでしょ。
printfの何を勉強してるの?
てか、
printf("%+fx%d ", a[i][j], j + 1);

わざわざprintf("a=%lf\nである", a)に変更して二次元配列aがすべて表示されるとでも思ったとしか考えようがない。
修正前と後及びエラーメッセージとにらめっこして自身で対処しなされ。

投稿2018/07/19 21:47

YomogiKOBO

総合スコア187

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

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

carnage0216

2018/07/20 14:14

>>修正前と後及びエラーメッセージとにらめっこして自身で対処しなされ。 そうさせて頂きます。 いつもいつもありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問