プロが教える店舗&オフィスのセキュリティ対策術

a^2=b^2+c^2の三平方の定理のフローチャートです
1<=a,b,c<=100の範囲の自然数で
定理をみたす自然数をもとめる問題なのですが
私が考えた下記のフローチャートを見てもらえませんか?
 開始
(1)a=0
(2)b=0
(3)c=0
(4)a=sqrt(pow(b,2)+pow(c,2))
(5)b=sqrt(pow(a,2)-pow(c,2));
(6)b=sqrt(pow(a,2)-pow(b,2));
(7)処理1<=a<=100NOならb=b+1,c=c+1で(4)へ
YES
(8)処理1<=b<=100NOならa=a+1で(5)へ
YES
(9)処理1<=c<=100NOならa=a+1で(6)へ
YES
(a,b,c)表示
終了
実行したら(2,1,1)になります
範囲のなかで上いがいで定理が成り立つabcを出したいのですが
どこが違うのかどうしたら良いのかアドバイスをください
一様c言語を書いてみました
できたら上の形でお願いします
a=0;
b=0;
c=0;
Label01:
a=sqrt(pow(b,2)+pow(c,2));
Label02:
b=sqrt(pow(a,2)-pow(c,2));
Label03:
c=sqrt(pow(a,2)-pow(b,2));
if (a>=1 && a<=100) {
/* YES 処理 */
printf("%d\n",a);
if (b>=1 && b<=100) {
/* YES 処理 */
printf("%d\n",b);
if (c>=1 && c<=100) {
/* YES 処理 */
printf("%d,%d,%d\n",a,b,c);
} else {
/* NO 処理 */
a=a+1;
printf("%d\n",c);
goto Label03;
}
} else {
/* NO 処理 */
a=a+1;
printf("%d\n",b);
goto Label02;
}
} else {
/* NO 処理 */
b=b+1;
c=c+1;
printf("%d\n",a);
goto Label01;
}
printf("a^2=b^2+c^2\n");
return 0;

A 回答 (1件)

「(4)へ」(および、Cのコードでのgotoの使用)といった表記は可読性を著しく落とします。

goto は使わないようにしましょう。
特に、質問者さんの挙げられた例でも、(7)~(9)あたりのYESとNOの処理の流れが、その文章からはさっぱり読み取れません。
たとえば、a を 1 ~100 の範囲で増やしていってそれぞれについて処理を行う場合、質問者さんの書くような表記では、
---ここから---
(1)a=1
(2)処理内容A
(3)処理内容B
(4)処理内容C
(5)もし a < 100 なら、a=a+1 して、(2)へ
---ここまで---
となりますが、これは、ループに関する記述が(1)と(5)に分かれているため、(2)~(4)部分の処理内容が増えてくるとわかりにくくなります。文章個条書きな段階では、
---ここから---
(1)aを1~100の範囲で変化させ、以下の処理を実行する
 (1-1)処理内容A
 (1-2)処理内容B
 (1-3)処理内容C
---ここまで---
のように記述した方が分かりやすいです。

以上が前振り。
以下、質問者さんの考えたアルゴリズムの問題について。

(不都合1) 変数a~cを整数に限定するような処理が無い
おそらく、a~cは整数型の変数だと思いますが、たとえば、
> (6)c=sqrt(pow(a,2)-pow(b,2));
これは、a=2, b=1 だったとしたら、c=1になります。(sqrt(3)=1.732…が、整数型変数への代入で切り捨て)
「(2,1,1)」という結果からしては、三平方の定理が成り立つような数値の組ではありません。

(不都合2) ループになっていません。
> (a,b,c)表示
> 終了
ここで数値を表示したら処理が終わってしまいます。
「a,b,cが三平方の定理の条件を満たしていれば、その数値の組を表示」するとしても、
条件を満たしていても満たしていなくても、次の数値を探すような処理にしなければなりません。

(不都合3)a,b,cの数値変化が正しくない
a,b,cの値を変化させる処理がばらけているため、「a,b,cのありえる数値を順番に全て調べる」ような数値変化になる保証がまったくありません。

以上のように、根本的に三平方の定理を満たす数値を探すようなアルゴリズムになっていません。

三平方の定理を満たす三数のもっとも単純(だけどムダの多い)算出方法は下記のようになります。
---ここから---
(1)a を 1 ~100 の範囲で変化させ、以下の処理を実行する
 (1-1) b を 1 ~100 の範囲で変化させ、以下の処理を実行する
  (1-1-1) c を 1 ~100 の範囲で変化させ、以下の処理を実行する
   (1-1-1-1) a*a == b*b + c*c かどうかを調べる。
    (1-1-1-1-YESの場合) (a,b,c)を表示する
---ここまで---
ただし、本来はaとbを定めれば、cは求まるのに、これだとムダにcをループ処理してます。
cをaとbから算出する場合、処理は以下のような感じ。小数ではなく整数として成り立つかどうかのチェックが必要ですので、その部分がちょっと複雑です。
「(int)(○○+0.5)」で、「0.5を足して小数点以下切り捨て」すなわち「四捨五入」の計算になります。
また、bがa以上の時は三平方の定理がが成り立つことはありませんから、bの繰り返し範囲も1~100ではなく、1~a-1で十分です。
それを改良すると、
---ここから---
(1)a を 1 ~100 の範囲で変化させ、以下の処理を実行する
 (1-1) b を 1 ~a-1 の範囲で変化させ、以下の処理を実行する
  (1-1-1) c =(int)(sqrt(a*a-b*b)+0.5)を計算する
  (1-1-2) a*a == b*b + c*c かどうかを調べる。(上述のcの算出が整数で成り立つかどうかのチェック)
   (1-1-2-YESの場合) (a,b,c)を表示する
---ここまで---
となります。C言語で書くなら、
---ここから---
for (a = 1; a <= 100; a++) {
for (b = 1; b <= a-1; b++) {
c = (int)(sqrt(a*a-b*b)+0.5);
if (a*a == b*b + c*c) {
printf("(%d,%d,%d)\n", a, b, c);
}
}
}
---ここまで---
    • good
    • 0

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