現在、C言語でプログラムを組んでいるのですが、複素数からなる行列の固有値を求めるプログラムがどうしてもつくることができません。
インターネットやプログラムのパッケージなどを調べてみたのですが、実数からなる行列の固有値を求めるプログラムしか載っておらず、勉強不足によりそれを複素数の場合に拡張することもできませんでした。
もしよければ、プログラムの組み方や実数のプログラムから複素数のプログラムへの替え方のこつ、もしくは「この本に載っていたよ」など、どんな情報でもかまいませんので教えて頂けないでしょうか?
すいませんがよろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

takashi5050 さんのお望みのアルゴリズムが載っているかどうか知りませんが、


技術評論社から出版されている Numerical Recipes in C に、
数値計算のプログラムが大量に載っています。
11章が固有値問題の数値計算法というタイトルなので、載ってるんじゃないかと思います

ちょっと高いですけど、それだけの価値はあると思います。
大き目の本屋さんなら置いていると思うので、覗いてみてください。

Numerical Recipes in C 日本語版
William H. Press・Saul A. Teukolsky・William T. Vetterling・Brian P. Flannery 共著
丹慶勝市・奥村晴彦・佐藤俊郎・小林誠 訳
B5変形 判 / 680 ページ / 本体価格 4757 円+税
ISBN4-87408-560-1

参考URL:http://bookweb.kinokuniya.co.jp/guest/cgi-bin/ws …
    • good
    • 0
この回答へのお礼

早速の情報をありがとうございます。
今週末にでも大きい本屋さんに行って来ます。

お礼日時:2001/11/07 00:39

一部訂正。


typedef double[2] complex;
    ↓
typedef double complex[2];
ですね。(最近Javaばかりやってたもんでつい...。)
コンパイラによっては、
typedef double *complex;
でないと、関数定義が通らないかもしれません。
    • good
    • 0

実数行列に関するアルゴリズムは分かっているわけですから、あとはそれを複素数に


拡張すればよいだけの話ですよね。(C++等の方がやりやすそうですが)

複素数をどのような形式で表現するかにもよりますが、例えば
typedef double[2] complex;
のようにしていたら、
void plus(complex c1, complex c2, complex result) {
 result[0] = c1[0] + c2[0];
 result[1] = c1[1] + c2[1];
}

void minus(complex c1, complex c2, complex result) {
 result[0] = c1[0] - c2[0];
 result[1] = c1[1] - c2[1];
}

void multiple(complex c1, complex c2, complex result) {
 result[0] = c1[0] * c2[0] - c1[1] * c2[1];
 result[1] = c1[0] * c2[1] + c1[1] * c2[0];
}

のように加算・減算・乗算を定義して(今回は除算はとりあえず不要でしょうから)
実数向けのアルゴリズムを置き換えればよいと思います。
    • good
    • 0
この回答へのお礼

お返事、ありがとうございます。
一度、書き換えてプログラムを作ってみようと思います。
ありがとうございました。

お礼日時:2001/11/07 00:44

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qエクセルで複素数の表し方

例えばisinθはエクセルでどうやって表せばよいのでしょうか?またその方法はexp(iδ)にも適用できますか?

Aベストアンサー

IMSIN関数が使えます。ただし「ツール」→「アドイン」で分析ツールを組み込む必要があります。以下はEXCELヘルプの内容です。

IMSIN(複素数)
複素数 サインを求める複素数を指定します。
COMPLEX 関数を使用すると、実数係数と虚数係数を指定して、複素数に変換することができます。

後半部分の意味はよく理解できませんが、IMLN(複素数の自然対数を返す)、IMLOG10(複素数の 10 を底とする常用対数を返す)関数も利用可能です。

Q行列A(l行m列)と行列B(m行n列)の積C(l行n列)を求めるプログラム

ヒントを頂きたいです。
よろしくおねがいします。

Aベストアンサー

行列の積を求めるプログラムは、過去にも、何回かでてきました。
参考URLのものは、固定のサイズですけど、
mallocで動的にサイズを確保するか、
計算可能な最大の大きさをあらかじめ決めておくか
することになると思います。

参考URL:http://okweb.jp/kotaeru.php3?qid=1391489

Q複素数

複素数について質問させて頂きます。

参考書には、
「複素数zが実数でない場合つまり、虚部が0でないときzは虚数である」という。

というように記載されていました。
私は複素数は常に虚数だと認識していましたがそうでない場合もあるのでしょうか?
複素数zが実数でない場合と記載されていたので複素数が実数の場合もあるのでは
ないかと考えた次第です。

つまり、
z=x+iy
(z:複素数、x,y:実数、i:虚数単位)
において、y=0の場合でもzを複素数と呼ぶのですか?
上記の場合、zは虚数ではないですが複素数とは言えるのでしょうか?

複素数の定義は、
実数x,yと虚数単位iを用いてz=x+iyの形で表すことのできる数です。
(定義にy≠0は特に記載されていませんでした。)

なので、z=x+iyにおいてy=0の場合は複素数とは言わないと考えています。

質問内容を整理しますと、
(1)複素数は常に虚数である
(2)z=x+iyにおいて、y=0のときzは複素数ではない
  複素数の定義にy≠0は必要なのでしょうか?


以上、ご回答よろしくお願い致します。

複素数について質問させて頂きます。

参考書には、
「複素数zが実数でない場合つまり、虚部が0でないときzは虚数である」という。

というように記載されていました。
私は複素数は常に虚数だと認識していましたがそうでない場合もあるのでしょうか?
複素数zが実数でない場合と記載されていたので複素数が実数の場合もあるのでは
ないかと考えた次第です。

つまり、
z=x+iy
(z:複素数、x,y:実数、i:虚数単位)
において、y=0の場合でもzを複素数と呼ぶのですか?
上記の場合、zは虚数ではないですが複素数...続きを読む

Aベストアンサー

>複素数の定義は、
>実数x,yと虚数単位iを用いてz=x+iyの形で表すことのできる数です。
>(定義にy≠0は特に記載されていませんでした。)
>
>なので、z=x+iyにおいてy=0の場合は複素数とは言わないと考えています。

どうしてそういう意味不明なことを?

z=x+iyであって,yについては何も条件がない(yが実数ということ以外)なら
yは実数であればなんでもいいということです
勝手に「yは0ではない」なんてつけてはいけません.

実数は複素数の一部です.
高校でそう習ったでしょう?
教科書にもそう書いてあるでしょう?

「zは複素数」という言及は「zが実数」というのを含みます.
「複素数zが実数ではない」というのが虚部が0ではないという意味です.

ちなみに
>複素数zが実数でない場合つまり、虚部が0でないときzは虚数である

こんな言い方はかなりマイナーです.
教科書や問題集で「虚数単位」という以外に
わざわざ「虚数」っていうことはほとんどないはずです.

Q複素数のプログラムの組み方

複素数のプログラムの組み方

今自分はy=exp(-jkx)という式のプロットをするプログラムを組んでいます。
しかしexpの()の中はdouble型しか定義できないということがわかったのでオイラーの
公式よりcos(kx)-isin(kx)と変換してプログラムを組んでいるのですがなぜか
y=xのグラフになってしまいます。isin(kx)の方に問題があると思いますが
#include <complex.h>もできています…
どなたか式の作り方を教えて頂けないでしょうか?
よろしくお願い致します。

Aベストアンサー

double complex k, x;
だと仮定して,
double complex y = cexp(I * k * x);
でよいと思いますが。
または,<tgmath.h>をインクルードして,
double complex y = exp(I * k * x);
とか。

あと,問題点がプロットにあるのか式にあるのかちゃんと区別した方がよいですよ。
例えばprintfで出力した時に値が正しいことは確認していますか。

Q複素数 実数 集合 濃度

複素数と実数について質問させて頂きます。

実数は有理数と無理数をあわせた数(複素数から虚部を除いた数)
と認識しています。

添付にイメージ図を記載しました。
このイメージ図が間違っているのでしょうか?

集合としては実数より複素数が大きいと思います。
しかし、複素数と実数の濃度は等しいと教えて頂きました。

濃度とは、有限集合でいうところの数だと認識しています。

集合として複素数が大きいのに、複素数と実数の濃度が等しい
事が不思議でなりません・・・
複素数の集合は実数の集合と虚数の集合を合わせたものなのに
なぜ、複素数と実数の数は等しくなるのでしょうか?


以上、ご回答よろしくお願い致します。

Aベストアンサー

Alice_44先生よりも素人っぽい説明をトライしてみます。

連続体濃度で考える前に加算濃度の無限集合を考えます。

最初に、二元数の無限集合が一元数の無限集合と一対一対応することを確認します。
二元数とは二次元座標系の様に、(X,Y)で表すことが出来る数です。
大きさが無限の碁盤の目を想像してください。
縦方向にXを割り当て、横方向にYを割り当てると、無限に大きな碁盤の目で全ての可算無限の二元数が割り当てられることが分かります。
つぎに、自然数Nをもってきて、碁盤の目を斜めに割り当てます。図を書くのが面倒なので言葉で説明すると、

(1,1)=1
(2,1)=2
(2,2)=3
(3,1)=4
(3.2)=5
(3,3)=6
(4,1)=7
 ・・
 ・・
 ・
と割り当てて行けば、すべての升目に自然数Nを一対一で対応させることができます。
したがって、二元数の可算無限の濃度は、自然数と同じ、つまりアレフ0であることが分かります。

連続体濃度でも同じように対角線で対応を考えると、実数Rと複素数X+Yiが一対一対応をすることが分かります。
(数学的にはここの詰めが甘いとこなのですが、イメージはつかみやすいと思います。)
このことから複素数と実数がおなじ濃度アレフ1を持つことが分かります。

連続体濃度の二元数は平面と考えることができます。したがって、上記のことは、直線の中にある点の数と、平面の中にある点の数が同じであるという、摩訶不思議なことを証明しています。
立体空間に中に取れる全ての点(=3元数)と、線分の中に取れるすべての点も一対一対応することが分かります。
まさに無限であることからの違和感がありますが、点を元とする無限集合は、直線でも、平面でも、立体でも、濃度が同じという事です。

ご参考まで。

Alice_44先生よりも素人っぽい説明をトライしてみます。

連続体濃度で考える前に加算濃度の無限集合を考えます。

最初に、二元数の無限集合が一元数の無限集合と一対一対応することを確認します。
二元数とは二次元座標系の様に、(X,Y)で表すことが出来る数です。
大きさが無限の碁盤の目を想像してください。
縦方向にXを割り当て、横方向にYを割り当てると、無限に大きな碁盤の目で全ての可算無限の二元数が割り当てられることが分かります。
つぎに、自然数Nをもってきて、碁盤の目を斜めに割り当てます。図...続きを読む

Q素数を求めるプログラム

素数を求める関数の作り方を調べていたら以下のような
プログラムを見つけました。
for文の中は奇数で割り切れるかどうかを調べているということで
いいのでしょうか??何故j*j<=kとなっているのでしょうか??
後、最後のreturn YES;はどのような場合実行されるのでしょうか??

#include<stdio.h>

#define YES 1
#define NO 0

int sosu(int k){
int j;
if(k == 2) return YES;
if(k % 2 == 0) return NO;
for(j=3;j*j<=k;j+=2){
if(k % j == 0) return NO;
}
return YES;
}

Aベストアンサー

int sosu(int k){ //実数kが素数かどうかを調べる関数
int j;
if(k == 2) return YES; //k=2ならば、kは素数である
if(k % 2 == 0) return NO; //kが偶数ならば、kは素数ではない
for(j=3;j*j<=k;j+=2){ //kが3以上の奇数のとき
if(k % j == 0) return NO; //k以外の奇数で割り切れれば、素数ではない
}
return YES; //上記の処理をくぐってくれば素数である
}

です。
y=SQRT(y)^2ですから、SQRT(y)以上の約数が出てくるはずがないんです。
ですから、それ以上の処理はしません。

Q代数学の基本定理と複素数体cより濃度が大きい環?

代数学の基本定理では、複素数を係数に持つ任意の、n次方程式は必ず、n個の複素数の根を持つ、とあります。私は、これは、複素数体cより濃度が大きい体を考えても無駄ということを意味すると思うので、一般に、複素数体cより濃度が大きい環を考えても無駄だと思うのですが、複素数体cより濃度が大きい環はあるのでしょうか?

Aベストアンサー

「複素数から複素数への写像の集合」Fは複素数体Cより濃度が大きいですよね。
Fの元f,gについて、
加法を f+g : z → f(z) + g(z)
乗法を fg : z → f(z)g(z)
と定義しましょう。

この時、零元は 0F : z → 0 、
fのマイナス元は -f : z → -f(z) であり、
交換法則・結合法則は満たします。

また、単位元は 1F : z → 1 、
fの逆元は f ≠ 0Fの時 f^(-1) : z → 1/f(z) であり、
交換法則・結合法則は満たします。

また、分配法則も満たすので、可換体になっていないでしょうか。

Q素数を求めるプログラム

1000以下の素数を求めるプログラムについての問題について考えているのですが、何故2の数のとき、乗除を行う回数が加算されないのかが分かりません。また、3のとき乗除を1回しか行わないのか分かりません。理論的に2が素数となるのは定義付けられているから必要ないのか、とも思ったのですがそれならcounter++で2が範囲にあるのに加算されないという理由がよくわかりません。
初歩的な問題ですみませんが回答頂けると有難いです。
プログラムは下記の通りです。

#include <stdio.h>

int main(void)
{
int i,no;
unsigned long counter = 0;

for (no = 2; no <= 1000; no++) {
for (i = 2; i < no; i++) {
counter++;
if (no % i == 0)
break;
}
if (no == i)
printf("%d\n" , no);
}

printf("乗除を行った回数:%lu\n" , counter);

return (0);
}

1000以下の素数を求めるプログラムについての問題について考えているのですが、何故2の数のとき、乗除を行う回数が加算されないのかが分かりません。また、3のとき乗除を1回しか行わないのか分かりません。理論的に2が素数となるのは定義付けられているから必要ないのか、とも思ったのですがそれならcounter++で2が範囲にあるのに加算されないという理由がよくわかりません。
初歩的な問題ですみませんが回答頂けると有難いです。
プログラムは下記の通りです。

#include <stdio.h>

int main(void)
{
in...続きを読む

Aベストアンサー

noが2のとき、

>for (i = 2; i < no; i++) {

このfor文は
for (i = 2; i < 2; i++) {
と同じですね。そうすると、i < 2 の条件を初回から満たしませんので、
このfor文の中身(counter++; など)をスキップします。
counterの値は不変です。

次に、noが3のとき、

>for (i = 2; i < no; i++) {

このfor文は
for (i = 2; i < 3; i++) {
と同じですね。そうすると、
iは2なので、i < 3 の条件を満たします。counter++; を実行します。
iをインクリメントし、3になります。そうすると、
i < 3 の条件を満たしませんので、for文のループを抜けます。
counterをインクリメントしたのは一度だけです。

Q複素数をより高い視点から

私は高校レベルの複素数には飽き足らず、いろいろ複素数について学んでいくうちにもっと専門的なレベルでの複素数について純粋に知りたいと思っています。学参には書いていないような、テイラー展開がどのように複素数と関係するのかなど、高校レベルよりも少し高いくらいのことが知りたいです。そこで大学での専門書の中で、入門書レベルの専門書で何かお勧めの書はごぞんじありませんか?ぜひ教えてください!!

Aベストアンサー

そうですねえ。読みやすさということなら、
志賀浩二「数学が育っていく物語2 解析性 」
はどうでしょう。

専門書とは言えませんが、テイラー展開と複素数の関係(解析性)なんかを、ほんとの専門書で学ぶ前にイメージしたい、っていうには非常によいかと。

QC言語<素数を求めるプログラム>

#include<stdio.h>
int j;
int prime(int n)
{
int i;

if(n < 2) return 0;
if(n == 2) return 1;
if(n%2 == 0) return 0;

for(i = 3; i*i<= n; i += 2){
if(n%i == 0) return 0;
}
return 1;
}

int main(void)
{
int n;

for(n=1; n <= 1000; n++)
{
if(prime(n)){

printf("%d\n",n);
j++;
}
}
printf("素数の個数は全部で %d 件見つかりました。\n",j);

return 0;
}

このプログラムは1から1000までの素数のみを表示させるプログラムでありますが、このアルゴリズムが全くわかりません。
int prime(int n)の中身のアルゴリズムがどういう仕組みになっているのかお分かりになりますでしょうか?

#include<stdio.h>
int j;
int prime(int n)
{
int i;

if(n < 2) return 0;
if(n == 2) return 1;
if(n%2 == 0) return 0;

for(i = 3; i*i<= n; i += 2){
if(n%i == 0) return 0;
}
return 1;
}

int main(void)
{
int n;

for(n=1; n <= 1000; n++)
{
if(prime(n)){

printf("%d\n",n);
j++;
}
}
printf("素数の個数は全部で %d 件見つかりました。\n",j);

return 0;
}

このプログラムは1から1000までの素数のみを表示させるプログラムであり...続きを読む

Aベストアンサー

「int prime(int n)」内についてですが、
if(n < 2) return 0;
 →2未満の数字は素数としない、つまり「1」の時は素数ではないと判断したい処理ですね
if(n == 2) return 1;
 →2の時は無条件に素数と判断する為です
if(n%2 == 0) return 0;
 →nを2で割った時のあまりが0だったら素数ではない、つまり(2より大きい)偶数の時は絶対素数ではないので偶数をはぶく為の処理ですね
for(i = 3; i*i<= n; i += 2){
if(n%i == 0) return 0;
}
 →割る数(i)を3から5、7、9・・・のように増やしていって、nを割ったときのあまりが0かどうか判断しています。
  例:n=9場合、i=3の時に9/3であまりが0になるので、9は3で割り切れるから9は素数じゃない!
  の処理をしています。
return 1;
 →で、最後のreturnですが、これは説明不要でしょか?
  ここに来るまで素数じゃないと判断されたらreturn 0で途中で処理を抜けています。
  つまりここまで来たら素数なのでreturn 1を返します。

で、よろしいでしょうか?

「int prime(int n)」内についてですが、
if(n < 2) return 0;
 →2未満の数字は素数としない、つまり「1」の時は素数ではないと判断したい処理ですね
if(n == 2) return 1;
 →2の時は無条件に素数と判断する為です
if(n%2 == 0) return 0;
 →nを2で割った時のあまりが0だったら素数ではない、つまり(2より大きい)偶数の時は絶対素数ではないので偶数をはぶく為の処理ですね
for(i = 3; i*i<= n; i += 2){
if(n%i == 0) return 0;
}
 →割る数(i)を3から5、7、9・・・のように増やし...続きを読む


人気Q&Aランキング

おすすめ情報