- ベストアンサー
可変次数の正方行列を引数にとる方法について
crew21の回答
- crew21
- ベストアンサー率26% (58/222)
オレはこれは、単純にdoubleの2次元配列で処理できない気がする。 No.1さんも言われている通り、そもそも「逆行列を求めたいもとの行列は、どこでどのように定義しますか?」ということになる。 やり方は幾つかあると思うけど、「可変」が条件なんだから、どうしたって動的な定義になる(よね?)。 例えば仮にこの実行ファイルが test.exe だった場合、第一引数で次数を指定するとしたら、test.exe 5 みたいな実行形式になる。 それをソース中で、doubleの2次元配列で表現しようとすると、 double test_matrix[ atoi(argv[1]) ][ atoi(argv[1]) ]; みたいになる。 でも配列の要素数は定数式じゃないとダメだから、コンパイルエラーになると思う(っていうかなります)。 だから質問者さんは、関数に2次元配列を引数として渡す前に、どうやって、可変の2次元配列を作るか。 或いはそれに相当するものを作るか、を先に考えるべきじゃないかな。 とりあえずここまで回答しとく。
関連するQ&A
- 二次元配列を引数として渡し、再び返す方法
c++を用いてます。 main関数内において、二次元配列(行列)の計算によって各成分の値を求め、 その二次元配列を関数の引数として渡し、成分を用いて計算した後、再び返す方法を知りたいです。 具体的には、ルンゲクッタ法を用いたプログラムで、 #include<iostream> : double g11(double D[][9],double x11~) double g12(double D[][9],double x11~) : int main(void) { (中略)double D[6][9]=などの定義をしています for(i=0;i<100;i+) { 行列の計算(積や逆行列の計算) ルンゲクッタ法 (ここでg11を用います) k111=h*g11(D,x11,…); : dx11=(k111+…)/6.0; : cout<<x11…<<endl; x11+=dx11; x12+=dx12; : } return 0; } double g11 (double D[][9],double x11…) { double dif; dif=D[0][0]*x11+D[0][1]*x12+… return(dif); } double g12 (double D[][9],double x11…) { double dif; dif=D[1][0]*x11+D[1][1]*x12+… return(dif); } : というようなプログラムです。エラーは出ないのですが、値が一瞬で発散してします。 ちなみに、D[6][9]は行列の積や逆行列の計算を行った結果得られた二次元配列です。 おそらくポインタをうまく使わないといけないことはなんとなく解るのですが…。 プログラムの説明が解りにくくて申し訳ないのですが、よろしくお願いいたします。
- 締切済み
- C・C++・C#
- 引数の可変
覚えたての引数の可変を使ってみた素人であります。(独学です 見よう見真似で書いた為、目茶苦茶だと思われます。 自分で簡単なexeファイルを作ってみていて 引数の可変が必要となったので付け足そうとしていたのですが、「引数の可変」部の他 意外にもfor文からもエラーが出ました(while使えば済む話なのですが) 今までfor文をあまり使わずwhile文ばかり使っていた為、for文の基本的な構文が失敗しているのかもしれません。折角だから使ってみようとした結果がこれです。 #include <stdio.h> #include <locale.h> #include "DxLib.h" #include <string.h> #include <stdarg.h> int i; ・・・略・・・ class CharsOut{ ____int ypixel; ____char *hangar; ____int size; ____int HowMany; ____int list; public: ____int CharsOuting(int HowMany,int ypixel,int size,...); }; int CharsOuting(int HowMany,int ypixel,int size,...){ ____va_start(list,HowMany); ____for (i=0;i<HowMany;i++){ ________printf("%s",va_arg(list,char *)); ____} ____va_end(list); ____return 0; } ypixel、size...といった変数等は気にしないでください。 成功していたらコードを足すつもりでした。 自分がやりたいことは、main関数から変数HowMany,*hangar等を受け取り 文字列*hangarを引数の分出力したいのであります。引数の可変は*hangarを何個か渡すつもりだったので使用しました。 こんな感じに使うつもりでしたc.CharsOuting(2,0,32,"I am ", "hangury"); ※リストは(int HowMany,int ypixel,int size,...)です ※ハングリーのスペルが違う等ということはとてつもなくどうでもいいことなのです。 自分で「main関数から*hangarを受け取り」と書いておきながらリストに*hangarがない時点でおかしいと思ってはいるのですが、記述の方法が分からないので書けません。 以下エラー (名前とか一部改変・不要な部分省略 1>------ ビルド開始: プロジェクト:(≡ω≡.), 構成: Debug Win32 ------ 1>コンパイルしています... 1>soucer.cpp 1>error C2040: 'i' : 'int' は 'int [5]' と間接操作のレベルが異なります。 1>error C2065: 'list' : 定義されていない識別子です。 1>error C2440: '=' : 'int' から 'int [5]' に変換できません。 1>配列型への変換はありませんが、参照またはポインタから配列への変換があります。 1>error C2446: '<' : 'int' 型から 'int *' 型への変換ができません。 1>整数型からポインタ型への変換には reinterpret_cast、C スタイル キャストまたは関数スタイル キャストが必要です。 1>error C2040: '<' : 'int [5]' は 'int' と間接操作のレベルが異なります。 1>error C2105: '++' には左辺値が必要です。 1>error C2065: 'list' : 定義されていない識別子です。 1>error C2065: 'list' : 定義されていない識別子です。 1>ビルドログは "file://c:\・・・\Debug\BuildLog.htm" に保存されました。 1>(≡ω≡.) - エラー 8、警告 0 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ========== 文章能力なくて申し訳ありません。 ご回答頂ければ幸いであります。宜しくお願いします。 OS:WinXP コンパイラ:Visual C++
- 締切済み
- C・C++・C#
- 配列を戻り値にして逆行列を求める関数
#include(stdio.h) int main(){ double a[4][4]={{1,2,0,-1},{-1,1,2,0},{2,0,1,1},{1,-2,-1,1}}; //入力用の配列 double inv_a[4][4]; //ここに逆行列が入る double buf; //一時的なデータを蓄える int i,j,k; //カウンタ int n=4; //配列の次数 //単位行列を作る for(i=0;i<n;i++){ for(j=0;j<n;j++){ inv_a[i][j]=(i==j)?1.0:0.0; } } //掃き出し法 for(i=0;i<n;i++){ buf=1/a[i][i]; for(j=0;j<n;j++){ a[i][j]*=buf; inv_a[i][j]*=buf; } for(j=0;j<n;j++){ if(i!=j){ buf=a[j][i]; for(k=0;k<n;k++){ a[j][k]-=a[i][k]*buf; inv_a[j][k]-=inv_a[i][k]*buf; } } } } //逆行列を出力 for(i=0;i<n;i++){ for(j=0;j<n;j++){ printf(" %f",inv_a[i][j]); } printf("\n"); } } という、4次元正方行列の逆行列を求めるプログラムがあるのですが これを複数の行列の逆行列が求められる関数にする場合を教えてください・・行列は配列で作ってるのでよくわかりません、お願いします
- ベストアンサー
- C・C++・C#
- (汎用的に)行列の積を求めるプログラム
L*M実行列A , M*N実行列B , M*N実行列C を引数として、A*BをCに代入するプログラムを作りたいと思っています。 具体的には、エラーがでるのはわかっていますがイメージとして void multiply(int L,int M,int N,double A[L][M],double B[M][N],double C[L][N]) { for(int l=0;l<L;l++) for(int n=0;n<N;n++) C[l][n]=0; for(int l=0;l<L;l++){ for(int m=0;m<M;m++){ for(int n=0;n<N;n++) C[l][n]+=A[l][m]*B[m][n]; } } } という感じです。Cを自分なりに学習したところ、「2次元配列を渡すには行or列数が少なくとも既知でないといけない」のは知識として得ているのですが、ではこの問題を回避して所望のプログラムを書け、と言われると行き詰ってしまいました。 卒論をするにあたり、種々のサイズの行列演算が必要なので、できるだけ効率的な関数を書いておきたいのですが、どうすれば一般の行列の積の演算が可能になるのでしょうか?
- ベストアンサー
- C・C++・C#
- Java 可変長引数と優先度
Java 可変長引数と優先度 こんにちは。c#初心者兼、java始めました です。 可変長引数の場合のオーバーロードの優先度について困っています(質問と言うより半分愚痴です)。 javaにも可変長引数ってありますよね。(ジェネリックの弱さにイライラしていたけれど)「javaも捨てたものじゃない」と感心しながら使っていると、いきなりコンパイルエラー。 sampleMethod(10, 20); と書いている部分でエラーが発生していました。 自分のメソッド定義を確認しみると、 void sampleMethod(int...); void sampleMethod(Object...); の2種類のオーバーロードがあり、ambiguousなため判別不能らしいです。 確かに、AutoBoxingされれば、int...だけでなく、Object...にもマッチしますが、どう考えてもBoxingしない方が優先度が高いはずです。というか、高く設定されるべきです。 個人的に基準にしているc#ではこのようなことは起きませんでした。 (あ、やっぱり捨てたものかもしれない ←心変わり早す(ry ) 試しにc#でInteger型のクラスを作り、(実際はタブーですが)暗黙のキャストを双方向でオーバーロードして実験してみました。 public class Integer // ここからc# { private int _value; //---------------------------- public Integer(int value) { _value = value; } //---------------------------- // Integer → int の暗黙の型変換 public static implicit operator int(Integer value) { return value._value; } // int → Integer の暗黙の型変換 public static implicit operator Integer(int value) { return new Integer(value); } //---------------------------- // javaの sampleMethod(int... values)に相当 public static void SampleMethod(params int[] values) { } // javaの sampleMethod(Object... values)に相当 public static void SampleMethod(params Object[] values) { } } そして、Integer.SampleMethod(10, 20); と書いてみると……問題……なし。 ちゃんと、SampleMethod(param int[] values)が選ばれていました。 つまり、(個人的には)java(コンパイラ)の方が不可解な動きをしているのです。 sampleMethod(int, int)とsampleMethod(Object, Object)があるときは問題ないので、可変長引数のときだけambiguousになるようです。 「それなら」と思い、sampleMethod(int, int...)とsampleMethod(Object, Object...)を作ってみましたが、やはりエラーが出ます。 何か良い解決策はあるでしょうか? 可変長じゃない引数のオーバーロードを大量に作ることと、片方の可変長をやめること以外でアドバイスをお願いします。 もしくは、「個人的には~だから、パクリのc#よりjavaの方が動きが正しいぞ!」という方がいらっしゃいましたら、ご意見ください。
- 締切済み
- Java
- 3×3行列ジョルダン標準正規
ジョルダン細胞の数と次数の考え方。 間違っていたら指摘して下さい。 3×3行列について (1)固有値が3つ異なる場合 α≠β≠γ それぞれの固有空間の階数(rank)は、2なので、それぞれの固有空間の次 元は1次元。 従って、ジョルダン細胞の次元は1次。1つの固有値に対するジョルダン細胞の数も1個。 J=J(α,1)+J(β,1)+J(γ,1) (2) 固有値が3重根の場合 (1)固有空間のrankが2の場合 固有空間の次元は、3-2=1次元。 固有ベクトルは、1つだけ。 よってジョルダン細胞は1個。 行列が3次なので、3次のジョルダン細胞が1個。 J=J(α,3) ここで、(A-αE)^2≠0、(A-αE)^3=0になるが、この計算は不要。 (2)固有空間のrankが1の場合 固有空間の次元は、3-1=2次元。 2次元上で独立な固有ベクトルは、2つ以上取れる。 ジョルダン細胞の数は2個。 3次元行列であるから、2個のジョルダン細胞は、2次1個と1次1個になる。 よって、J=J(α,1)+J(α,2) (3)固有値が2個が重根、1個単根の場合。 固有値=α(重根)、βとする。 (1)αに対する固有空間のrankが2の場合 固有空間の次元は、3-2=1次元。 ジョルダン細胞の数は1個。 1次元だからαの固有ベクトルは1個だけ。 βは単根だから、固有空間の次元は1次元で固有ベクトルは1個だけでジョルダン細胞の次元も1次。3次元行列だから、αに対するジョルダン細胞の次数は、3-1=2次元でなければいけない。 よって、J=J(α,2)+J(β,1) (2)αに対する固有空間のrankが1の場合 固有空間の次元は3-1=2次元。 2次元なので、固有ベクトルは2つ以上取れる。 ジョルダン細胞は2個でそれぞれ1次。 βに対するジョルダン細胞は上記と同じ。 よって、J=J(α,1)+J(α,1)+J(β,1)
- ベストアンサー
- 数学・算数
- 二次元配列の引数渡し
二次元配列を関数の引数として渡し、 その配列を戻り値として呼び出し元の変数に返したいです。 具体的にはルンゲクッタ法で微分する関数の引数を行列で扱いたいです。 for (i=0;i<N;i++){ for (j=0;j<N;j++){ y[i][j]=rand(); } } K1=h*ff(t,y); K2=h*ff(t+h/2,y+K1/2); K3=h*ff(t+h/2,y+K2/2); K4=h*ff(t+h,y+K3); Ka=(K1+2*K2+2*K3+K4)/6; double ff(int t,double y[][]){ ここで return y[][]; のような形で二次元配列を戻り値として変数に返したいのです。 } C言語初心者なのでいまいちよくわかりません、 宜しくお願いいたします。
- ベストアンサー
- C・C++・C#
- C++、コンストラクタの引数の数を可変にしたい
次のようなプログラムを作ろうとしています。 あるクラスComponentは DIM(整数)次元(要素数)のdouble型配列と ここで DIM は別のところでconstで宣言されています。 (他にもいくつか変数を持っているのですが話に関係ないので割愛します) とりあえずこんな感じにしたいです。 class Component{ public: double x[DIM]; Component(double x,double y,double z, ,,,,,); //コンストラクタ } ここでコンストラクタComponentは引数にDIM個の実数をとり、たとえば DIM = 3のとき Component obj(1.0,2.0,3.0); と宣言したら obj.x[0]=1.0 obj.x[1]=2.0 obj.x[2]=3.0 となるようにしたいのです。 むろん代入すること自体は代入すればよいのですが 外で宣言されているDIMによってコンストラクタの引数の数が変わってしまいます。 こういう時はどのような解決策があるでしょうか。 今書いたのと全然違うやり方でもかまいません。 (ただ何個も何個もコンストラクタをオーバーロードするのは避けたいです。 いろんなDIM次元で実験がしたく、きりがありません)。 よろしくお願いいたします!
- ベストアンサー
- C・C++・C#
お礼
ありがとうございます。 コンパイルした後に渡すのではなく、普通に 変数を宣言して渡すと思っているのですが・・・ 説明不足でした。すいません