ページ 1 / 1
複素数
Posted: 2006年12月10日(日) 21:37
by キリコ
どうもはじめまして。
わからないことがあって質問させていただきます。
複素数の割り算についてなのですが、まず
#include <stdio.h>
#include <math.h>
void xy_rt(double x,double y,double *pr,double *pt)
{
*pr=sqrt(x*x+y*y);
*pt=atan(y/x);
}
main()
{
double x1,y1,x2,y2,r1,t1,r2,t2;
if (scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2)!=4){
printf("4つ数字をいれてください\n");exit(1);
}
xy_rt(x1,y1,&r1,&t1);
xy_rt(x2,y2,&r2,&t2);
printf("答え=%6.2lf,%6.2lf\n",(r1/r2)*cos(t1-t2),
(r1/r2)*sin(t1-t2));
}
というプログラムができるのですが、atanは値域が-2/πから2/πでx>0,y>0またはx>0,y<0という制限があるのでx,yの符号から判断し、0から2πの角度を出力する2変数関数を新たに定義して書き換えてほしいのです。
本や、検索してもわからなかったので、自分なりにかんがえてz=a+biと考えて、やるのかとか、sinとcosの逆関数から判断するのかと思ったのですが、どうも角度を出力することができませんでした。
どなたかわかる方がいらしたら教えてください、お願いします。
ついでなのですが、実数部がゼロの場合に対応させるしかたも組み込んでくれるとありがたいです。
Re:複素数
Posted: 2006年12月10日(日) 22:18
by box
> 複素数の割り算
三角関数を使わずに、
a+bi (a+bi)(c-di) (ac+bd)+(bc-ad)i
---- = ------------ = ----------------
c+di (c+di)(c-di) c^2+d^2
という式(cとdの少なくとも一方は0でない)で
計算してもいいのですか?
Re:複素数
Posted: 2006年12月10日(日) 22:44
by キリコ
返信ありがとうございます。
「ライブラリ関数atanのかわりにx,yの符号から判断し、0から2πの範囲の角度を出力する2変数関数を新たに定義」となっていたので、そのような角度が出ればいいと思います。
多分*pt=atan(y/x); を新たにするのかな?と思うのですが・・・どうもまだわかりません。
Re:複素数
Posted: 2006年12月11日(月) 08:47
by mas
>「ライブラリ関数atanのかわりにx,yの符号から判断し、0から2πの範囲の角度を出力する2変数関数を新たに定義」
これを見る限り複素数でなくても良さそうですね。
x, y, atan(y/x)の正負に注目しましょう。
x y atan(y/x) θ
正 正 正 0~π/2
負 負 正 π~3π/2
となりますね。
つまりatanの正負に加えてx, yの正負で場合分けすれば良いのです。
以下サンプルです。
double theta = atan(y, x);
if(theta >= 0) {
if(x >= 0)
return theta;
else
return theta + M_PI;
}
atan(y/x)が負のときは自分で考えてみてください。
Re:複素数
Posted: 2006年12月11日(月) 08:55
by mas
何かいろいろ間違えてしまったような…
サンプルとして挙げたソース
× atan(y, x)
○ atan(y/x)
そもそもatanやacos等を使ってはいけないのかな?
だとしたらすみません。
Re:複素数
Posted: 2006年12月12日(火) 07:59
by キリコ
返信ありがとうございます。使ってよいとか悪いとかは書いてなく、2変数関数を新たに定義とかしか書いていないのですが、「ライブラリ関数atanのかわりに」のかわりという意味は使わないということでしょうかねぇ。微妙です。とりあえず、atanを使って角度を求める方法しかわかっていないのでなんともいえないのですが。
>acos等
これは私の勝手な思いつきなのですがacos asinでできそうな気がするのですがどうでしょう?
Re:複素数
Posted: 2006年12月12日(火) 21:04
by キリコ
すみませんacos asinじゃ値域0~πと-π/2~π/2ですね。
うーん難しいです。
Re:複素数
Posted: 2006年12月12日(火) 21:53
by mas
acos, asinを使っても良いのなら簡単にできますよ。
上のほうにatanの例を挙げましたが、x, yの正負に注目してπを足せばよいので。
Re:複素数
Posted: 2006年12月13日(水) 21:53
by キリコ
返信ありがとうございます。
>acos, asinを使っても良いのなら簡単にできますよ。
>上のほうにatanの例を挙げましたが、x, yの正負に注目してπを足せばよいので。
すみませんがよければacos, asinのときどういった感じになるのか示してくれませんか?ちょっと自分の知識不足で理解できていないので・・・。
「atanのかわり」となると今のところacos, asinしか思い浮かびませんよねぇ、うーん。
Re:複素数
Posted: 2006年12月14日(木) 19:11
by キリコ
ほんとうにいろいろとすみませんでした。ある情報によるとatanを使ってよいと人伝えに聞きました。
まだ考えていませんが、もし私より早くできそうだったら教えてくださると助かります。よろしくお願いします。
Re:複素数
Posted: 2006年12月14日(木) 19:39
by 管理人
入力した2点から角度さえ求めたらいいんですか?
でしたらatan2ですぐ出来るんじゃないでしょうか。
実現しようとさせていることが違ったらごめんなさい。
Re:複素数
Posted: 2006年12月14日(木) 19:52
by 管理人
↑クリックで画像拡大↑
標準関数を使っていいということなんですが、めちゃそれだと簡単じゃないですか?
#include <stdio.h>
#include <math.h>
int main(void){
double x1=4.0,y1=1.0,x2=5.0,y2=3.0;
printf("%fラジアン\n",atan2(y2-y1,x2-x1));
return 0;
}
こういうことじゃなかったですか?(_ _||)
Re:複素数
Posted: 2006年12月14日(木) 20:26
by mas
昨日レスしようと思ってたのに忘れてました。
> 管理人さん
atan2は私も考えてましたけど、どうですかね。
おそらくatan(やacos,asin)を使ってatan2相当の関数を自前で実装するという課題かと予想しているのですが。
> キリコさん
atanを使った方法は上で挙げてるのものを少し改良するだけなので、
もしわからないのなら、どこがわからないのかを教えてください。
Re:複素数
Posted: 2006年12月14日(木) 22:42
by 管理人
Re:複素数
Posted: 2006年12月17日(日) 12:42
by キリコ
atan2(y,x)と動作が同じになるか検討するのが、その次の問題でした。masさん、管理人さん、私の説明不足で申し訳ないです。
今は、とりあえず前にmasさんが場合わけした例を使って、作ってみています。
Re:複素数
Posted: 2006年12月20日(水) 22:45
by キリコ
{double z,f; z=atan(y/x);
if(z >0) { if(x >0) return (z);
if(x < 0) z=z + pi; return (z); }
if(z < 0) { if(x > 0) f= pi*2; z=z + f; return (z);
if(x < 0) z=z + pi; return (z); }
if(z ==0) { if(x >0) return (0);
if(x < 0) return (pi); }
if(x == 0){ if(y>0) return (pi/2);
if(y<0) return (pi*3)/2; } }
としたのですが、どうも270度のときが二分の3πがでません。この場わけであっているでしょうか?どなたか教えてください。お願いします。
そもそもこのプログラムでいいのでしょうか?
Re:複素数
Posted: 2006年12月20日(水) 22:54
by 管理人
ちょっとプログラムがごちゃごちゃしすぎて、どこに括弧がどこで閉じているかわからなくなっていませんか?
きちんと字下げしてみたほうがいいですよ。
間違いを減らすためにも。
前にも聞いたかもしれませんが、どうやって字下げしています?
{
{
double z,f; z=atan(y/x);
if(z >0) {
if(x >0)
return (z);
if(x < 0)
z=z + pi;
return (z);
}
if(z < 0) {
if(x > 0)
f= pi*2;
z=z + f;
return (z);
if(x < 0)
z=z + pi;
return (z);
}
if(z ==0) {
if(x >0)
return (0);
if(x < 0)
return (pi);
}
if(x == 0){
if(y>0)
return (pi/2);
if(y<0)
return (pi*3)/2;
}
}
return 0;
}
このように綺麗に書いて対応を確認してみてください。
Re:複素数
Posted: 2006年12月20日(水) 23:09
by indent
インデントは、gnu indent などを使うと、楽にチェック出来ますよ。
ただ、スタイルはいくつかのパタンに制限されるけど。
Re:複素数
Posted: 2006年12月20日(水) 23:35
by キリコ
if(y<0)
return (pi*3)/2;
のところだと思うのですが・・・πは定義しているのでいいと思います。x=0でy<0が270度にちゃんと対応しているとおもうのですが・・・。なぜ3π/2が出ないのか
<管理人さん
< このように綺麗に書いて対応を確認してみてください。
おっしゃるとおり見にくいですね。今度から気をつけたいと思います。
<indent
<gnu indent
どう使うのかわかりませんが、がんばってみます。ありがとうございます。
Re:複素数
Posted: 2006年12月21日(木) 00:31
by mas
x == 0 のときはy/xを計算してしまうとまずいので、atan(y/x)の前に条件分岐させましょう。
if(z < 0) のときの一つ目のreturn以降は実行されません。
Re:複素数
Posted: 2006年12月21日(木) 01:16
by キリコ
masさん返信ありがとうございます。
<atan(y/x)の前に条件分岐させましょう。
なるほど。ありがとうございます。
<if(z < 0) のときの一つ目のreturn以降は実行されません。
どうすればよいのでしょうか?
Re:複素数
Posted: 2006年12月21日(木) 01:23
by 管理人
return を行うと、そこ以降の処理は行われません。
インデントしたプログラムをみて、処理を確認してくださいと言うのは、その部分をみてほしかったのですが、
if文は括弧をつけないとその直後、;、までしか条件の処理が行われないことはご存知ですよね?
条件文による複数の処理を行いたい場合は括弧で囲む必要があります。
Re:複素数
Posted: 2006年12月21日(木) 01:58
by キリコ
管理人さんありがとうございます。
<ご存知ですよね?
実は知りませんでした。
つまりif(z < 0) のときのは
if(z < 0) {
if(x > 0){
f= pi*2;
z=z + f;
return (z);
}
if(x < 0){
z=z + pi;
return (z);
}
}
とやって初めの部分は
double z,f;
if(x == 0){
if(y>0)
return (pi/2);
if(y<0)
return (pi*3)/2;
}
z=atan(y/x);
とやればいいでしょうか?
Re:複素数
Posted: 2006年12月21日(木) 02:04
by キリコ
字下げしているのですが、表示すると、上記のようになってしまうみたいなんですが・・・。Windowsだから?
Re:複素数
Posted: 2006年12月21日(木) 02:21
by 管理人
ウェブならどこの掲示板でもHPでも半角スペースやタブインデントは省略されてしまうんです。
これはHTMLの仕様なのだと思います。
半角スペースやタブインデントを有効にして表示したければ
<pre>と</pre>で囲んでやってください。
きれいに表示されます。ちなみに<>は半角で入力してください。
今半角で入力してしまうとそれ自体見えないタグになってしまうので全角で書いています。
括弧の対応についてはそれで大丈夫だと思います。
Re:複素数
Posted: 2006年12月21日(木) 02:30
by キリコ
管理人さんいろいろとありがとうございます。
Re:複素数
Posted: 2006年12月21日(木) 05:01
by 管理人
またお気軽にお聞きくださいませ☆