無題

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
しょしょしょしんしゃ

無題

#1

投稿記事 by しょしょしょしんしゃ » 16年前

すみません
質問です 
外部から2つの2次元平面上の点の座標を与えた時、
その2点を通る直線の方程式を求める関数の作成。
2次元平面上の点は
typedef struct point2{
float x;
float y;
}POINT2
を用いて表すこと。
関数名および引数は各自に決めてよい。
なお直線が座標軸と平行になるときも正しい方程式が
得られるようにする。
というものです 自分なりに考えましたが、
上手く ビルトできませんでした
どこが 間違っていますか?
#include <stdio.h>

typedef struct{
	double x;
	double y;
}POINT;

typedef struct{
	double a;
	double b;
	double c;
}LINE;

int getline(LINE *cf,POINT p,POINT q){
	int md;
	double eps=1.e-8;
	double dx,dy;
	double a,b;

	dx=q.x-p.x;
	dy=q.y-p.y;

	md=0;
	if(fabs(dy)>eps) md+=1;
	if(fabs(dy)>eps) md+=2;
cf>a=cf>b=cf>c=0;
switch(md){
case 0:
break;
case 1
cf>a=1;
cf>c=p.x;
break;
case 2:
cf>b=1;cf>c=p.y;
break;
case 3:
a=dy/dx;
b=p.y a*p.x;
f(fabs(b)>eps){
cf>a=-a;
cf>b=1.;
cf>c=0.;
}else{
cf>a=a/b;
cf>b=1./b;
cf>c=1.;
}
break;
default:
printf("illegal case;md=%d\n",md);
}
return md;
}

int main(){
 POINT p,q;
 LINE cf;
 double x,y;
 int md;

do
printf("点1の座標=");
scanf("%lf%lf",&x,&y);
p.x=x;
p.y=y;
printf("点2の座標=");
scanf("%lf%lf",&x,&y);
q.x=x;
q.y=y;
md=getline(&cf,p,q);
printf("直線の方程式:ax+by_=c\n");
printf("[md=%d]係数:a=%f,b=%f,c=%f\n",md,cf.a,cf.b,cf.c);
}while(md>0);
printf("終了\n");
return 0;
}
たぶん 間違いは多いと思われます よろしくお願いします

rom

Re:無題

#2

投稿記事 by rom » 16年前

・トピックにはわかりやすい名前を付けましょう
・コードはきちんと字下げしましょう
・コンパイルエラーが出たならどんなエラーが出たか書きましょう
・あきらかに間違いとわかる構文ミスや括弧記載ミス位直して投稿しましょう

しょしょしょしんしゃ

Re:2次元平面上のプログラミング

#3

投稿記事 by しょしょしょしんしゃ » 16年前

すみません
訂正版です
#include <stdio.h>
#include <math.h>

     typedef struct{
	double x;
	double y;
    }POINT;

    typedef struct{
	double a;
	double b;
	double c;
     }LINE;

    int getline(LINE *cf,POINT p,POINT q){
	int md;
	double eps=1.e-8;
	double dx,dy;
	double a,b;

	dx=q.x-p.x;
	dy=q.y-p.y;

	md=0;
	if(fabs(dy)>eps) md+=1;
	if(fabs(dy)>eps) md+=2;
 cf->a = cf->b = cf->c = 0;
        switch(md){
          case 0:
          break;
          case 1:
          cf->a=1;
          cf->c=p.x;
          break;
          case 2:
          cf->b=1;
c         f->c=p.y;
break;
case 3:
a=dy/dx;
b=p.y-a*p.x;
if(fabs(b)>eps){
cf->a=-a;
cf->b=1.;
cf->c=0.;
}else{
cf->a=a/b;
cf->b=1./b;
cf->c=1.;
}
break;
default:
printf("illegal case;md=%d\n",md);
}
return md;
}

int main(){
 POINT p,q;
 LINE cf;
 double x,y;
 int md;

printf("aのx座標=");
scanf("%f",&x);
printf("aのy座標=");
scanf("%f",&y);
p.x=x;
p.y=y;
printf("bのx座標=");
scanf("%f",&x);
printf("bのy座標=");
scanf("%f",&y);
q.x=x;
q.y=y;
md=getline(&cf,p,q);
if(p.x==q.x && p.y==q.y){
	printf("直線の方程式はたくさんあります\n");
}else if(p.x==q.x){
printf("直線の方程式:x=%f\n",cf.a);
}else if(p.y==q.y){
	printf("直線の方程式:y=%f\n",cf.b);
}else{
printf("直線の方程式:%fx+%fy=%f\n",cf.a,cf.b,cf.c);
}
return 0;
}
エラーはでませんでしたが、うまく実行できませんでした。
たぶん
 
else if(p.x==q.x){
printf("直線の方程式:x=%f\n",cf.a);
}else if(p.y==q.y){
printf("直線の方程式:y=%f\n",cf.b);

の部分に間違いがありそうです

non

Re:2次元平面上のプログラミング

#4

投稿記事 by non » 16年前

>printf("直線の方程式:ax+by_=c\n");
なぜ、直線の方程式をこのように出力しなければいけないのですか?
一般的には y=ax+b だと思いますが。

>double eps=1.e-8;
これは、課題で与えられたものですか?

>md=getline(&cf,p,q);
mdも課題で与えられていますか?

初級者

Re:無題

#5

投稿記事 by 初級者 » 16年前

直線の式は
y=ax+b でも
ax+by=c でも
結局同じことです。

non

Re:無題

#6

投稿記事 by non » 16年前

y=ax+b なら、a,bは一意的に決まりますが、
ax+by=c は、a,b,cの解の組み合わせは無限に存在します。
a,b,cが最小の整数という条件があれば別ですが。a,b,cはfloatのようですし、
条件を与えるべきではありませんか?

しょしょしょしんしゃ

Re:無題

#7

投稿記事 by しょしょしょしんしゃ » 16年前

すみません
問題からしっかり直します。
  外部から2つの2次元平面上の点の座標を与えた時、
  その2点を通る直線の方程式を求める関数の作成。
  なお直線が座標軸と平行になるときも正しい方程式が
  得られるようにする。
というもので やはり #deine を使用した方がいいのでしょうか?

YuO

Re:無題

#8

投稿記事 by YuO » 16年前

> y=ax+b なら、a,bは一意的に決まりますが、
> ax+by=c は、a,b,cの解の組み合わせは無限に存在します。

2次元における直線の式はax + by = cであって,y = ax + bではありません。
後者では,直線x = 0を表現出来ませんから。
そもそも,問題中に,
> なお直線が座標軸と平行になるときも正しい方程式が
> 得られるようにする。
とあるので,y = ax + bという式では,題意を満たしません。


> というもので やはり #deine を使用した方がいいのでしょうか?

#defineは関係ないです。


> うまく実行できませんでした。

「うまくいかない」といったような表現は,技術系掲示板において,何も書いていないのと同じです。

・入力した値
・予想した結果,できたら「なぜそう予想したのか」もあるとなお良いです
・実際の結果
を具体的に示して下さい。

回答する側もエスパーではないので,「予想した結果」がわからず,答えようが無くなります。

しょしょしょしんしゃ

Re:無題

#9

投稿記事 by しょしょしょしんしゃ » 16年前

すみません やはり 考え直しました。
以前のやり方では 自分で考えていませんでしたので
全く分かりませんでしたが もう1度作り直すと 
このように 短く終え、
エラーは無く 上手く 実行できました。

何か 工夫するところはありませんか?
あれば 是非 指摘してください。
#include <stdio.h>
#include <math.h>

typedef struct point2{
	float x;
	float y;
}POINT2;
void POINT2_polar_form(POINT2 a,POINT2 b){
}POINT2;

#define SLOPE(pt1,pt2,pt3,pt4) ((pt3)-(pt4))/((pt1)-(pt2));
#define INTERCEPT(pt1,pt2,pt3,pt4) ((pt3)-((pt3)-(pt4))/((pt1)-(pt2))*(pt1));


int main(void){
	float c,d,e,f,g,h;
	printf("aのx座標=");
	scanf("%f",&c);
    printf("aのy座標=");
	scanf("%f",&d);
	POINT2 a={c,d};
    printf("bのx座標=");
	scanf("%f",&e);
    printf("bのy座標=");
	scanf("%f",&f);
	POINT2 b={e,f};
	g=SLOPE(a.x,b.x,a.y,b.y);
	h=INTERCEPT(a.x,b.x,a.y,b.y);
	if(a.x==b.x && a.y==b.y){
		printf("2点が同じ点なのでたくさんあります\n");
	}else if(a.x==b.x){
		printf("x=%f\n",a.x);
	}else if(a.y==b.y){
		printf("y=%f\n",a.y);
	}else{
    printf("y=%fx%+f\n",g, h);
	}
return 0;
}

>・入力した値
     a.x=c=1 a.y=d=2 b.x=e=3 b.y=f=4 ....①
もしくは a.x=c=1 a.y=d=2 b.x=e=1 b.y=f=4 ....②
あるいは a.x=c=1 a.y=d=2 b.x=e=1 b.y=f=2 ....③

>・予想した結果,できたら「なぜそう予想したのか」もあるとなお良いです
 ①y=x+1
 ②x=1 にずっと続く
 ③無限
//普通に考えた、計算したところ このような予想になります。
>・実際の結果
①y=1.0000x+1.0000
 ②x=1.0000
 ③2点が同じ点なのでたくさんあります
                  //予想と同じでした。
>を具体的に示して下さい。
このようで いいですか?

YuO

Re:無題

#10

投稿記事 by YuO » 16年前

> 何か 工夫するところはありませんか?

ざっと見た感じだと,
・POINT2_polar_formのまわりがおかしい (コピペミス?)
・SLOPE,INTERCEPTともに0除算の可能性
# 0除算は未定義動作

g, hともに使うのはy = ax + bの形になる場合のみですから,その場合にのみSLOPEやINTERCEPTを呼び出せばよいです。

あと,標準CまたはC++のようですから,関数形式マクロをやめてinline関数にする方が,副作用等の問題もなく良いかと思います。


>>を具体的に示して下さい。
>このようで いいですか?

よいです。
今回の場合,予想した結果と実際の結果が等しかったので,「望むべき動作が得られた」と言えるわけです。
# 未定義動作が隠れてしまうわけですが,それは仕方がないです。

異なっていた場合,回答者はそれを手がかりに「間違いであろう箇所」の指摘ができますし,
掲示板に書く前にこれをまとめることで,掲示板に質問するより先にバグを見つけることができるかもしれません。
「予想と異なる場所」を小さくしていくと,最終的にバグに突き当たりますから。

フリオ

Re:無題

#11

投稿記事 by フリオ » 16年前

 
> #define SLOPE(pt1,pt2,pt3,pt4) ((pt3)-(pt4))/((pt1)-(pt2));
> #define INTERCEPT(pt1,pt2,pt3,pt4) ((pt3)-((pt3)-(pt4))/((pt1)-(pt2))*(pt1));

 思ったことを少し、

 どうして、構造体のメンバをばらばらにして渡しているのでしょうか。
構造体で渡した方がすっきりすると思います。

 解釈によるかもしれませんが、この課題は"SLOPE"と"INTERCEPT"をまとめた
直線の式を求める関数またはマクロを要求しているのではないでしょうか。

 先の回答で言われているように、この方法だと"x == a(aは定数)"の場合は、
別に対応しなければいけないので、
"直線が座標軸と平行になるときも正しい方程式が得られるようにする。"
という条件に反するのではないでしょうか。
 

しょしょしょしんしゃ

Re:無題

#12

投稿記事 by しょしょしょしんしゃ » 16年前

>どうして、構造体のメンバをばらばらにして渡しているのでしょうか。
構造体で渡した方がすっきりすると思います。

私もそう思いました。
何度も方法を見つけましたが
#define SLOPE(pt1,pt2) (pt1.y-pt2.y)/(pt1.x-pt2.x)
#define INTERCEPT(pt1,pt2) (pt1.y-SLOPE(pt1,pt2)*pt1.x)
  とやっておいて、
POINT2 p1, p2;
printf("y=%fx%+f\n",SLOPE(p1,p2), INTERCEPT(p1,p2));
[pre]
 で実行しようとすると
 うまくまとめれませんでした。
 すっきりときれいに並べるいい方法を教えてください。

閉鎖

“C言語何でも質問掲示板” へ戻る