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

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

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

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

Q&A

解決済

4回答

821閲覧

double型のデータの確認方法、その他教えて下さい。

ryusei_12

総合スコア11

C

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

0グッド

0クリップ

投稿2020/04/18 09:12

自分は、現在2点から辺の長さを求めるプログラムを作成しています。

そこで疑問が出てきたので、いくつかお答えいただければ恐縮です。
まずは、以下に簡単なコードを記載します。

C

1#include <stdio.h> 2#include <stdint.h> 3 4#define TOL 0.1 5 6typedef struct _point {//座標(X,Y) 7double x;//ここはdouble_tを使用すべき?? 8double y; 9} POINT; 10 11void perimeter(POINT* point1, POINT* point2, double value;) { 12 //ここでまず構造体のメンバの値が空でないか確認 13 //...... 14 //求まった値を出力引数(value)に格納 15} 16int main() { 17 POINT point1;//point1のx,yを格納 18 POINT point2;//point2のx,yを格納 19 //何かしらの処理をして構造体に値を代入 20 perimeter(&point1, &point2, &value); 21 22}

簡潔で申し訳ないのですが、以上のようなコードを作成しようとしています。

そこで質問させていただきたいのが以下になります。
・perimeter関数の引数である構造体のメンバがNULL?空?きちんと入力されているか確認したいと考えたのですが、
if ((point1->x == NULL)...で確認を行おうとしたら、"invalid operands to binary == ...."と記載されてコンパイルに失敗しました。
他の確認方法はありますでしょうか?というのが1点です。

・上記コードにも記載したのですが、マク定義で記載した"TOL"についてです。
調べたら、一応これが、求まった値による許容誤差だということはわかったのですが、、、、以下のことが曖昧で分かっていません。
//求まった答えが例えば(14.234567(double)の場合、
->TOL(0.1)なので、14.2?と答えが出るようにコードを作成すればいいということでしょうか?
的はずれな考えをしていたら申し訳ないです。

以上です。
長々と申し訳ありませんが、よろしくお願いします。

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

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

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

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

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

guest

回答4

0

回答ではありませんが、2点間の距離を求める関数なら <math.h> にありますよ。

C

1#include <stdio.h> // printf 2#include <math.h> // hypot 3 4typedef struct { double x, y; } POINT; 5 6void perimeter(const POINT *p1, const POINT *p2, double *value) 7{ 8 *value = hypot(p1->x - p2->x, p1->y - p2->y); 9} 10 11int main(void) 12{ 13 POINT p1 = { 10.5, 1.5 }, p2 = { 1.5, 12.5 }; 14 double val; 15 perimeter(&p1, &p2, &val); 16 printf("%.1f\n", val); 17}

投稿2020/04/18 17:12

kazuma-s

総合スコア8224

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

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

ryusei_12

2020/04/19 02:29

回答ありがとうございます。 すでに用意されているんですね、、、 知らなかったです。 ありがとうございまうす
guest

0

ベストアンサー

Cでは、変数は必ず何らかの値を持っています。使っていないからNULL、とかいうものではありません(そもそもNULLってなんだか、ちゃんと調べて下さい)

きちんと入力されているか確認したい

「きちんと入力された」場合に、ある範囲に収まっていて、そしてその範囲が変数の扱える値より狭いのであれば、変数の値を事前に「きちんと入力されていない」状態に設定しておくことで「きちんと入力された」ことを確認できるかも知れません。
整数型などでは結構難しい場合もありますが、浮動小数点ならNaN(Not a Number)という特異な値があるのでこれを無効の印として

C

1#include <math.h> //NaNの扱いに必要 2 3 POINT p = {nan(""),nan("")}; //NaNに初期化 4//このあとpに値を与える...はず。 5 if( isnan(p.x)){//NaNかどうかを判別 6//値が設定されなかったことを検出 7 }

とする手は使えそうな気がします(gccなどではコンパイルオプションに-lmをつけてmathライブラリをリンクしないといけません)


(別の内容は別の質問として分けるべきだとは思います)

一応これが、求まった値による許容誤差だということはわかった

「求まった値による許容誤差」という言葉はちょっと意味不明ですが、
浮動小数点演算の誤差ということでしょう。

例えば、次のプログラムの結果はどうなるでしょう?

#include <stdio.h> int main(void) { double sum = 0; for (int i = 0; i < 1000; i++) { sum += 0.1; } if(sum==100){ printf("sum == 100\n"); }else{ printf("sum != 100\n"); } return 0; }

よほどの特殊な環境でない限りsum != 1が表示されるでしょう。
これは、コンピュータの内部では値が2進数で扱われていて、10進数で「綺麗」に見える小数が2進数では有限ケタで表せないことが(しばしば)あるからです。詳しく知りたければ"浮動小数点 誤差"あたりをキーに検索していただくとして、そういうわけでコンピュータで浮動小数点を扱う場合は、「誤差」を意識しないといけません。単純な==による比較は事実上機能しないのです。

誤差がある程度以下であると判断できるなら、

#include <stdio.h> #include <math.h> #define TOL 0.01 int main(void) { double sum = 0; for (int i = 0; i < 1000; i++) { sum += 0.1; } if(fabs(sum-100)<TOL){ printf("sum == 100\n"); }else{ printf("sum != 100\n"); } sum = 0; for (int i = 0; i < 1001; i++) { sum += 0.1; } if(fabs(sum-100)<TOL){ printf("sum == 100\n"); }else{ printf("sum != 100\n"); } return 0; }

ということで期待する結果を求めることができます。
TOLは、あなたが「これ以下は誤差だ」と判定する値を設定して下さい。

投稿2020/04/18 12:50

編集2020/04/19 09:18
thkana

総合スコア7703

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

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

ryusei_12

2020/04/19 04:53

すみません。 教えていただいた内容でコードを記載してみたのでですが、わからなくなりました、、、 なぜ以下でうまく動作しないいのか教えていただけますでしょうか? ・2点の座標が同座標にあたらないかチェックしています。 #define TOL (0.1) if (((point1->x - point2->x) < TOL) && ((point2->x - point1->x) < TOL) && ((point1->y - point2->y) < TOL) && ((point2->y - point1->y) < TOL)) { return ERROR;//point1,point2が同じ座標を指していないか確認 } このような内容で確認したのですが、 以下の数値を入力した場合、ERRORが返されました。 座標1x,y = (1.2, 2) 座標2,x,y= (1.1, 2) なぜかおわかりになりますでしょうか、、、? コメントからで申し訳ないです。
thkana

2020/04/19 09:14

移動先の質問で負の数への対応の不備が指摘されましたので修正します。
guest

0

“void perimeter(POINT* point1, POINT* point2, double value;) ”ではなく
void perimeter(POINT* point1, POINT* point2, double *value)ですね?
・・・返却値(value)はポインタで受け取って値を代入、セミコロン';'は不要。
また、 「何かしらの処理をして構造体に値を代入」と言っているのだから「構造体のメンバの値が空でないか確認」はなぜ?・・・何も入らない可能性が有るなら、構造体初期化時にx,yに特定の値(後の処理で設定されない値)を入れればどうでしょう?

投稿2020/04/18 09:48

編集2020/04/18 10:01
cateye

総合スコア6851

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

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

cateye

2020/04/18 09:57 編集

メンバー変数が変わっても、それさえ見れば有効かどうかが分かるため、構造体が有効かどうかのフラグ(みたいなの)を、追加するほうがいいと思っていますが。
ryusei_12

2020/04/19 02:20

なるほど。フラグ的なものを用意するのもありですね。。。 ありがとうございます。参考にさせていただきます。
guest

0

C言語のコードを組む場合には、デバッグできる環境を整えましょう。
WindowsであればVisualStudio、LinuxでもEclipseなど、探せば他にもあるでしょう。
これらの環境上では、ソースコードの任意の行で実行を止め、変数のナカミを確認でき、1行づつ実行してコードの動作を確認することもできます。
これであなたのやりたいことができるかと思います

・perimeter関数の引数である構造体のメンバがNULL?空?

NULLというのは0ポインタを表すものですんで、doubleと比較はできません。
そもそもローカル変数で定義した変数はデタラメの値を持つので、0との比較は意味ありませんね

投稿2020/04/18 09:24

編集2020/04/18 09:27
y_waiwai

総合スコア88042

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問