依存関係のあるfor文に対するOpenMP

このQ&Aのポイント
  • C言語での並列計算にOpenMPを使用するために、依存関係のあるfor文を効率的に並列化する方法について教えてください。
  • 組み合わせ数の計算に取り組む際、依存関係のあるfor文をOpenMPで並列化する方法を教えてください。
  • C言語でのプログラムで依存関係のあるfor文をOpenMPを活用するための工夫方法を教えてください。
回答を見る
  • ベストアンサー

依存関係のあるfor文に対するOpenMP

初めて質問させていただきます。これまでC言語を勉強していましたが、最近になってgccでも並列計算ができることを知り、その勉強を始めています。今、並列化の醍醐味を味わってみようと思い、組み合わせ数の計算(nCk)に取り組んでいます。まず、OpenMPを使っていない場合のプログラムを作りました。下記のプログラムが、それです。正しく動作していると思います。 しかし、このプログラムでは、for文の前後に依存関係があるため、このままでは並列化ができません。 if文を使って依存関係がないバージョンも試してみましたが、物凄く遅くなってしまいした。 このようなプログラムでOpenMPを活用するには、どのように工夫すれば良いでしょうか? どなたかご教授をお願いいたします。 追伸 下記のプログラムでは、100個の中から5つ取り出す際の組み合わせ数を計算しています。 #include <stdio.h> #include <stdlib.h> #include <math.h> #define PARA_NUM 100 int main(void) { unsigned long long int i; unsigned int kk0, kk1, kk2, kk3, kk4; unsigned int parameter_num = 5; unsigned int pn[parameter_num]; for( i = 0; i < parameter_num; i++ ) { pn[i] = PARA_NUM - parameter_num + (i+1); } i = 0; for( kk0 = 0; kk0 < pn[0]; kk0++ ) { for( kk1 = kk0+1; kk1 < pn[1]; kk1++ ) { for( kk2 = kk1+1; kk2 < pn[2]; kk2++ ) { for( kk3 = kk2+1; kk3 < pn[3]; kk3++ ) { for( kk4 = kk3+1; kk4 < pn[4]; kk4++ ) { i++; } } } } } printf("%d_C_%d: %lld\n", PARA_NUM, parameter_num, i); return 0; }

質問者が選んだベストアンサー

  • ベストアンサー
  • ki073
  • ベストアンサー率77% (491/634)
回答No.5

No.4のお礼欄について 配列kをprivateにしていますがちゃんと機能するのか心配です。 (ポインタみたいなものなので問題があるように思いますがどうなんでしょうか?) それとcriticalが一番中のループにあるのでものすごい回数実行されます。効率はがた落ちになります。なるべく外にした方が良いです。 書き直したものを後に示します。(不必要だと思われるところは取り除いています) openMPなしで、real 0m8.614sです。 openMPあり(core数4)だとreal 0m2.571sで約3倍になっています。それなりに速くなっています。 time ./a.out で測定した結果です。 #include <stdio.h> #define PARA_NUM 200 int main(void) { long kk0, kk1, kk2, kk3, kk4; long i; long parameter_num = 5; long pn[parameter_num]; long sum; long sum_max = 0; long sum_min = PARA_NUM*parameter_num; long sum_min0, sum_max0; for( i = 0; i < parameter_num; i++ ) { pn[i] = PARA_NUM - parameter_num + (i+1); } #pragma omp parallel for private(kk0, kk1, kk2, kk3, kk4, sum, sum_min0, sum_max0) schedule(static, 1) for( kk0 = 0; kk0 < pn[0]; kk0++ ) { sum_max0=0; sum_min0=PARA_NUM*parameter_num; for( kk1 = kk0+1; kk1 < pn[1]; kk1++ ) { for( kk2 = kk1+1; kk2 < pn[2]; kk2++ ) { for( kk3 = kk2+1; kk3 < pn[3]; kk3++ ) { for( kk4 = kk3+1; kk4 < pn[4]; kk4++ ) { sum = kk0+kk1+kk2+kk3+kk4; if ( sum_max0 < sum ) { sum_max0 = sum; } if ( sum_min0 > sum ) { sum_min0 = sum; } } } } } #pragma omp critical { if ( sum_max < sum_max0 ) { sum_max = sum_max0; } if ( sum_min > sum_min0 ) { sum_min = sum_min0; } } } printf("max: %d\n", sum_max); printf("min: %d\n", sum_min); return 0; }

kitten_in_kobe
質問者

お礼

ki073さま、 お返事有り難うございました。教えていただいたプログラムを実際に自分でも試してみました。物凄く早くて感動しました。 また、1つ前のプログラムのうように配列 k を使って計算させてみたところ、物凄く遅くなりました。こういうところを工夫すると、格段に計算が早くなるのですね。とても良い勉強となりました。 critical宣言についても、意味することがよく分かりました。for文の一番内側では計算の待ち時間の問題もあり、一番外側にしなければならないことが良く分かりました。 schedule は本などで見たことはありましたが、scheduleの有無でどれだけ計算時間が変わるかは試したことがありませんでした。今回、schedule を付けたり外したりしながら、その効果を確認することができました。 これからも少しずつ並列計算の勉強していきます。また分からないことが出てきたら、こちら質問したいと思っておりますので、その際もよろしくお願いいたします。今回は何度も丁寧に教えてくださり、本当に有り難うございました。

kitten_in_kobe
質問者

補足

「お礼の欄」に書き忘れたことがありましたので、ここに少しですが書かせていただきます。今後の僕にとって、配列やfor文の中の関数に対する並列化の処理が必要になります。今回教えていただいたプログラムを参考にしながら、少しずつ勉強を進めていきたいと思っています。分からないことがあった場合、改めてこちらのサイトで質問させていただこうと思いますので、その際もよろしくお願いいたします。 これで質問を終了したいと思います。 今回は、何度も教えてくださり、本当に有り難うございました。

その他の回答 (4)

  • ki073
  • ベストアンサー率77% (491/634)
回答No.4

No.3の修正 綴りの間違いです。ciritalではなくcriticalですね。

kitten_in_kobe
質問者

お礼

ki073さま、 ご連絡が遅くなりました。 いただいたアドバイスを活用しながら、いろいろと試してみました。 最終的に、正しく動作したプログラムを下記に添付します。 ki073さんがおっしゃっている通り、critical宣言を使うと、物凄く効率が落ちますね。やはり配列に一旦入れて、for文を抜けた後に処理する工夫が必要なようです。 今後は、一番内側のfor文の中に関数がある場合についても取り組みたいと思っています。どのようにすべきかなど、まだまだ知らないことや分からないことがありますので、改めてOKWave上で質問したいと思っております。 もしよろしければ、その際も、アドバイスをいただければと思います。 今回は、とても有益なアドバイスを有り難うございました。 #include <stdio.h> #include <stdlib.h> #include <math.h> #include <malloc.h> #include <time.h> #include <omp.h> #define PARA_NUM 200 int main(void) { unsigned long long int i; int j; unsigned long long int ii; unsigned long long int kk0, kk1, kk2, kk3, kk4; unsigned int parameter_num = 5; unsigned int pn[parameter_num]; unsigned int k[parameter_num]; int sum; int sum_max = 0; int sum_min = 1000; double t1, t2; for( i = 0; i < parameter_num; i++ ) { pn[i] = PARA_NUM - parameter_num + (i+1); } i = 0; t1 = omp_get_wtime(); omp_set_num_threads(THREADS_NUM); #pragma omp parallel for private(ii, kk0, kk1, kk2, kk3, kk4, k, sum, j ) \ shared(sum_max, sum_min) \ reduction(+:i) for( kk0 = 0; kk0 < pn[0]; kk0++ ) { ii = 0; for( kk1 = kk0+1; kk1 < pn[1]; kk1++ ) { for( kk2 = kk1+1; kk2 < pn[2]; kk2++ ) { for( kk3 = kk2+1; kk3 < pn[3]; kk3++ ) { for( kk4 = kk3+1; kk4 < pn[4]; kk4++ ) { ii++; k[0] = kk0; k[1] = kk1; k[2] = kk2; k[3] = kk3; k[4] = kk4; sum = 0; for( j = 0; j < parameter_num; j++ ) { sum += k[j]; } #pragma omp critical { if ( sum_max < sum ) { sum_max = sum; } if ( sum_min > sum ) { sum_min = sum; } } } } } } i += ii; } t2 = omp_get_wtime(); printf("\n"); printf("# wall clock time: %lf sec\n", t2-t1 ); printf("%d_C_%d: %lld\n", PARA_NUM, parameter_num, i); printf("max: %d\n", sum_max); printf("min: %d\n", sum_min); printf("#-----------------------------------------------\n"); return 0; }

  • ki073
  • ベストアンサー率77% (491/634)
回答No.3

No.2の補足欄について No.1の回答と同じように考えればできるはずです。 j=0; の位置で各threadのmaxとminを覚えておくprivate変数を初期化します。 カウンタとして使った i += j; の位置には、最大値、最小値の計算をreductionではできないので(FORTRANは使えるようです) 効率の落ちるのを覚悟でcirital宣言して各ループで計算した値から、最大値最小値を求めるか、 それとも、最大値用と最小値用にpn[0]個分の配列を確保して、一旦その配列に記憶させておいて、ループを抜けた後に計算する方法が使えるように思います。

kitten_in_kobe
質問者

お礼

何度も回答してくださり、本当に有り難うございます。 private変数の初期化とcritical宣言を試してみます。 配列の処理やfor文の中の処理が出来ると、今後、様々なことが出来きるようになるので、僕にとってはとても重要な内容です。 ただ、実際にそれらを試せるのは来週の月曜日になります。お返事が遅くなりますが、自分の力で上手く出来たかどうかや新たな質問などを、来週の月曜日か火曜日にご報告させていただきます。 また、ki073さんの方で追加のアイデアがありましたら、ぜひ、教えてください。 今回も、本当に有り難うございました。

  • ki073
  • ベストアンサー率77% (491/634)
回答No.2

今回のものは変数iがループの中で他から参照されていませんので特殊なケースです。 依存関係はありつつもループ自体どの順番に実行しても答えは変わらないので、もっとエレガントな方法があるかも知れません。 実際に実行してみると、実行時間は並列化してもそう速くなりませんでした。 kk0の小さい時は、内部のループの回数がものすごく多く、kk0が大きくなるにつれて、回数が少なくなってきます。 threadをkk0の値に関わらず均等に割り振っているようで、kk0の小さいthreadが最後まで残ってしまいそれが律速になっているかもしれません。schedule 指示節を加えて調整した方がよいように思います。

kitten_in_kobe
質問者

お礼

再度の回答、有り難うございます。 今後、進みたい方向は、変数iの計算そのものではなく、for文の一番内側で行う計算を、効率良く処理することです。 例えば、下記のような感じです。 そこで、for文の前後の依存関係を適切に処理しなければ、効率の良い並列化が難しいと思い、まずは、最初の質問に書いた問題を解いてみようと思いました。 for( kk0 = 0; kk0 < pn[0]; kk0++ ) { for( kk1 = kk0+1; kk1 < pn[1]; kk1++ ) { for( kk2 = kk1+1; kk2 < pn[2]; kk2++ ) { calc(num, parameter_num, output, A); } } }

kitten_in_kobe
質問者

補足

「お礼の欄」に書いた内容とプログラムでは、正しく説明できていませんでしたので、ここに改めて書かせていただきました。下記のプログラムのように、組み合わせられる値、0-1-2-3-4や1-2-3-4-5の数値の和を求めて、その最大値と最小値を求めたいとします。これが変数iそのものを求めるではなく、for文を効率よく並列化して、素早く求めたいと思っているという意味です。何度も説明をして申し訳ありません。 for( kk0 = 0; kk0 < pn[0]; kk0++ ) { for( kk1 = kk0+1; kk1 < pn[1]; kk1++ ) { for( kk2 = kk1+1; kk2 < pn[2]; kk2++ ) { for( kk3 = kk2+1; kk3 < pn[3]; kk3++ ) { for( kk4 = kk3+1; kk4 < pn[4]; kk4++ ) { k[0] = kk0; k[1] = kk1; k[2] = kk2; k[3] = kk3; k[4] = kk4; sum = 0; for( j = 0; j < parameter_num; j++ ) { sum += k[j]; } if ( sum_max < sum ) { sum_max = sum; } if ( sum_min > sum ) { sum_min = sum; } } } } } }

  • ki073
  • ベストアンサー率77% (491/634)
回答No.1

変数iが依存関係がありますねえ。 並列化はできるだけ外のforで行う方が良いので5重のforの一番外でできないか考えてみます。プログラムの骨格をできるだけ変えないようにしてみました。 変更場所だけだけを書きますと、 i = 0; #pragma omp parallel for private(j, kk0, kk1, kk2, kk3, kk4) reduction(+:i) for( kk0 = 0; kk0 < pn[0]; kk0++ ) { j=0; for( kk1 = kk0+1; kk1 < pn[1]; kk1++ ) { for( kk2 = kk1+1; kk2 < pn[2]; kk2++ ) { for( kk3 = kk2+1; kk3 < pn[3]; kk3++ ) { for( kk4 = kk3+1; kk4 < pn[4]; kk4++ ) { j++; } } } } i += j; } こんな感じでいかがでしょうか。jはあらかじめ宣言しておいてください。 これで一番外側のforで依存関係がなくなるはずです。 短時間で実行が終わるので全然効果は分かりませんが、適当に時間がかかるように内部にループを追加したら、並列化していることは確認できました。

kitten_in_kobe
質問者

お礼

お返事、有り難うございます。 依存関係を解消するのに、このようなアイデアがあるとは、まったく思いつきませんでした。今後、さらに多くのfor文を追加していきたいと思っているので、このアイデアを使って、より内側のfor文も並列化できないか取り組んでみます。 もし、ki073さんの方で追加のアイデアがありましたら、ぜひ、教えてください。 今回は、本当に有り難うございました。

関連するQ&A

  • C言語プログラムの並列化について

    OpenMPを用いて以下のC言語プログラムを並列化させようと考えています。 (sumの部分は今は単純な足し算ですが、kk0~kk4を用いた複雑な計算を考えています。) ------------------------------------------------------------------------------ #include <stdio.h> #include <time.h> #define PARA_NUM 200 int main(void) { long kk0, kk1, kk2, kk3, kk4; long i; long parameter_num = 5; long pn[parameter_num]; long sum; long sum_max = 0; long sum_min = PARA_NUM*parameter_num; long sum_min0 = PARA_NUM*parameter_num; long sum_max0 = 0; for( kk0 = 0; kk0 < PARA_NUM-4; kk0++ ) { for( kk1 = kk0+1; kk1 < PARA_NUM-3; kk1++ ) { for( kk2 = kk1+1; kk2 < PARA_NUM-2; kk2++ ) { for( kk3 = kk2+1; kk3 < PARA_NUM-1; kk3++ ) { for( kk4 = kk3+1; kk4 < PARA_NUM; kk4++ ) { sum = kk0+kk1+kk2+kk3+kk4; if ( sum_max0 < sum ) {sum_max0 = sum;} if ( sum_min0 > sum ) {sum_min0 = sum;} }}}}} printf("max: %d\n", sum_max0); printf("min: %d\n", sum_min0); return 0; } ------------------------------------------------------------------------------ 以上のプログラムを以下のように書き変えました。 ------------------------------------------------------------------------------ #include <stdio.h> #include <time.h> #define PARA_NUM 200 int main(void) { long kk0, kk1, kk2, kk3, kk4; long i; long parameter_num = 5; long pn[parameter_num]; long sum; long sum_max = 0; long sum_min = PARA_NUM*parameter_num; long sum_min0 = PARA_NUM*parameter_num; long sum_max0 = 0; #pragma omp parallel for private(kk0, kk1, kk2, kk3, kk4, sum, sum_min0, sum_max0) schedule(static,1) for( kk0 = 0; kk0 < PARA_NUM-4; kk0++ ) { sum_max0=0; sum_min0=PARA_NUM*parameter_num; for( kk1 = kk0+1; kk1 < PARA_NUM-3; kk1++ ) { for( kk2 = kk1+1; kk2 < PARA_NUM-2; kk2++ ) { for( kk3 = kk2+1; kk3 < PARA_NUM-1; kk3++ ) { for( kk4 = kk3+1; kk4 < PARA_NUM; kk4++ ) { sum = kk0+kk1+kk2+kk3+kk4; if ( sum_max0 < sum ) {sum_max0 = sum;} if ( sum_min0 > sum ) {sum_min0 = sum;} }}}} #pragma omp critical { if ( sum_max < sum_max0 ) {sum_max = sum_max0;} if ( sum_min > sum_min0 ) {sum_min = sum_min0; } }} printf("max: %d\n", sum_max); printf("min: %d\n", sum_min); return 0; } ------------------------------------------------------------------------------ インテルコンパイラ(icl)にてコンパイルした後、 windows7に標準で搭載されているelapsedtimeで実行時間を測定した結果、 上のプログラムは 2239milliseconds 下のプログラムは446millisecondsとなりました。(cpuは8コア) 8コア使うため実行時間は1/8に近づくと考えていましたが1/5程度となってしまいました。 下のプログラムより良い並列処理をするアルゴリズムはあるのでしょうか。 また#pragma omp criticalの構文は現在の位置が最適なのでしょうか。

  • for文

    整数を読み込んで、その値を0までカウントダウンしながら表示するプログラム作りたいのですが、 while文ではできたのですが、for文ではうまくいきません。 どこが間違っているのでしょうか? OS:Windows XP C++Builder X パーソナル #include <stdio.h> int main(void) { int i; int num; printf("整数を入力してください:"); scanf("%d", &num); for(i = num; i <= 0; --i) { printf("%d", i); } return 0; } 宜しくお願いします。

  • for文

    #include <stdio.h> int main(void) { int i; int sum=0; int num, tmp; printf("整数は何個かな:"); scanf("%d",&num); for(i=0; i<num; i++){ printf("No.%d:",i+1); scanf("%d",&tmp); sum+=tmp; } printf("合計値は:%d\n",sum); printf("平均値は:%.2f\n", (double)sum/num); return(0); } 上の文のforの箇所を for(i=1; i<=num; i++){ printf("No.%d:",i); scanf("%d",&tmp); sum+=tmp;   } としても結果的に同じですよね? どっちでもいいかどうか迷ってます。教えて下さい。

  • 簡単なfor文

    #include <stdio.h> int main(void) { int n; int i; for(n=0 ;n<10;n++){ for(i=0; i<=n ;i++){ printf("*"); } printf("\n"); } return(0); } こういったプログラムを実行すると、以下のように表示されるのですがなんででしょうか? * ** *** 以下略 自分の考えですと、*は毎回一つしか表示されずに改行されると思うのですが・・・ * * * * 以下略 i個分の*を表示するなどという指示をプログラムはなされていないと思うのですがなぜなんでしょうか? 一つ目のfor文では10回ループが繰り返され改行 二つ目のfor文で*を永遠に表示 といった僕の解釈ではおかしいですよね。 当方C言語初心者で、周りに聞く人がいないため教えていただけると非常に助かりますm(__)m

  • OpenMPのリダクション演算を自分でする方法

    OpenMPでプログラムを並列化しているのですが、以下の内積を並列化する際にreduction演算をしなくてはなりません for( i=0; i<N; i++ ){  r += x[i] * y[i]; } ↓ #pragma omp for reduction(+:r) for( i=0; i<N; i++ ){  r += x[i] * y[i]; } このように、for文に対してreduction節を入れてスレッド並列化するのが普通ですが、ここでBLASというライブラリを使いたいので、reductionを自分でしたいと考えています int INC = 1; int n = i_end - i_start; for( i=i_start; i<i_end; i++ ){  r += ddot_( &n, &(x[i_start]), &INC, &(y[i_start]), &INC ); } /* reduction here */ 0~N-1までの配列の要素を、自分でスレッドに分けて、i_start~i_endまでの要素の内積を各スレッドがddot_関数を使って計算します その後、reductionの計算をする必要があるのですが、一体どうすればreduction演算ができるのか分かりません どなたか分かる方、ご教授ください なお、スレッド並列版のBLASは使わない予定です あくまで、自分でスレッド並列化を行ない、その中で逐次版BLASを呼び出すという方向で考えています

  • OpenMPのことで悩んでいます

    現在、OpenMPを用いてOpenCVのライブラリを並列実行可能な形にしています。 その中で、配列のリダクションを行う場所があるのですが、その部分をどう書き換えればいいのか悩んでいます。 for( i = 0; i < height; i++ )//画像の高さ { for( j = 0; j < width; j++ )//画像の幅 { if( image[i * step + j] != 0 ) //エッジ抽出後の画像データ for(int n = 0; n < numangle; n++ ) { int r = cvRound( j * tabCos[n] + i * tabSin[n] ); //極座標空間への変換 r += (numrho - 1) / 2; int index = (n + 1) * (numrho + 2) + r + 1; //#pragma omp critical //{ accum[index]++; //極座標に対応する配列accumへの軌跡の投票 //} } } } 上がそのコードです。配列accumの要素をインクリメントする際に、データアクセスの競合が起こってしまいます。 その部分の上に「#pragma omp critical」と入れればアクセスの競合は防げるのですが、速度が200倍程度遅くなってしまい、使い物になりません。 なんとか配列の要素に対するリダクション処理を行いたいです。 OpenMPで配列のリダクションをする際の定石等あれば教えていただきたいです。

  • for文

    以下のプログラムのforの条件文がなぜこれで動くのかよくわからないので 教えていただけないでしょうか? #include<stdio.h> int main(void) { int i; char str[] = "ABC"; char *ptr = "123"; for(i=0;str[i];i++) putchar(str[i]); putchar('\n'); for(i=0;ptr[i];i++) putchar(ptr[i]); putchar('\n'); printf("str = \"%s\"\n",str); printf("ptr = \"%s\"\n",ptr); return(0); }

  • while for/ if else/do while文を使い”640968592”の各数字を独立させて取り出すことは可能でしょうか?

    忙しい中失礼します。 今以下のようなプログラミングを組もうとしています。 1.”640968592”といった9桁の数字を入力→scanfで入力(これは出来ます) 2.各桁の数字を独立させて取り出す:”6” ”4” ”0” ”9” ”6”・・・といった具合に(これも一応出来ます) 3.偶数桁は2倍する   2桁目:4x2=8   4桁目:9x2=18   6桁目:8x2=16   8桁目:9x2=18 そして、私の場合、以下のようなプログラムになるのですが、これがなんとも不細工な感じがし、スマートにプログラムを変更したいと思っています。 抱えている問題:while for/ if else/do while文などを用いて、下記のプログラムを書き直すことは可能なのでしょうか?例え出来たとしても、文int=num1~num35までの定義も減らすことは可能なのでしょうか? 手も足も出ない・・・ プログラム内容 #include <stdio.h> #include <stdlib.h> #include <math.h> int main() { int num1,num2,num3,num4; /*8 9桁目*/ int num5,num6; /*7桁目*/ ・ ・ ・ int num15,num16; /*2桁目*/ int num17; /*1桁目*/ int num19,num20,num21,num22,num23,num24,num25; int num26,num27,num28,num29,num30,num31,num32; int num33,num34,num35; printf("Write the SIN: "); scanf ("%d", &num1); num2=num1 / pow(10, 8); //9桁目 num3=num1 / pow(10, 7); //8桁目 num4=num3 % 10; num5=num1 / pow(10, 6); //7桁目 num6=num5 % 10; ・ ・ ・ num15=num1/pow(10, 1); //2桁目 num16=num15%10; num17=num1%10; //1桁目 num19=num4*2; //8桁目計算 num20=num19/10; num21=num19%10; num22=num20+num21; ・ ・ ・ num31=num16*2; //2桁目計算 num32=num31/10; num33=num31%10; num34=num32+num33; system("pause"); return 0; } こんなのが直ぐにプログラムとして早く組めるようになりたい・・・ どうしても頭に浮かばないのです。アドバイス等あればお願いします。 <使用環境:フリーソフト(Borland?)C ANSI C>

  • for文を別のint内で定義し、初めのint文内で呼び出す??? 何という名のプログラム名?ですか???

    毎度毎度忙しい中失礼します。現在<私のプログラム>を基に<参照プログラム>のようにプログラムを作り変えようとしていますが、正直お手上げ状態です。 どうしても<参照プログラム>に基づいてプログラムを組まなければならないのです。 どこがお手上げ状態かといえば、<参照プログラム>を参考にすると、int multInts(int x, int y)内の条件の組み方が<私のプログラム>内でどのようにして組めばいいのかが全くもって分かりません。かなり考えても分からないレベルです・・・私にとっては。 int multInts(int x, int y)の定義の仕方を真似て<私のプログラム>でも真似てみるのですが・・・出来ないのです。何をどう直せば良いのでしょうか???初期化でtra=0;とすると、表示は"0"になったりするし・・・。簡単かと思われるかもしれませんが・・・私にとってはかなり難しいのです。 ”丸投げ”みたいな感じで恥ずかしいのですが、どうかアドバイスだけでも下さい。お願いします。 出力結果 1.5桁数字入力:"12345"と入力 (これは出来ます) 2.偶数桁のみ抽出して2倍にする→"14385" (最不明部: <参照プログラム>内のmultInts内の条件を<私のプログラム>内でどのようにして組むのかが分かりません) 3.各桁の数値を足し合わせる→1+4+3+8+5=21(不明部: 2.が出来ないので出来ません) 4.その数値が”妥当”か”不当”かをDOS?画面に表示(不明部:2.と3.が出来ないので出来ません) <私のプログラム> #include <stdio.h> #include <stdlib.h> #include <math.h> int main() { int num,tra; int inpt=5; int inptnum; int sum=0; //#define 0 printf("5桁入力; "); scanf("%d", &num); if (num==0){ printf("その値は0です。 \n"); } else{ for(inpt ; inpt >=1 ; inpt--) { if(inpt%2 == 0) { inptnum = pow(10,inpt-1); tra = (num/inptnum)%10; //printf("%d",tra*2); tra=(tra*2)/10+(tra*2)%10; printf("%d",tra); } else{ inptnum = pow(10,inpt-1); tra = (num/inptnum)%10; printf("%d",tra); } sum += tra; } printf("\n %d\n",sum); sum= sum%10; if(sum==0) { printf("妥当な数値です。\n"); } else { printf("不当な数値です。\n"); } } system("pause"); return 0; } <参照プログラム> #include <stdio.h> #include <stdlib.h> int main(){ int multInts(int x, int y); int num1,num2,answer; printf("間にスペース設けて2つの値入力: "); scanf("%d%d", &num1, &num2); answer = multInts( num1, num2); printf("%d * %d=%d\n", num1, num2, answer); system("pause"); return 0; } int multInts(int x, int y) { int result = 0; int i; for (i=1 ;i<=y ;i++) { result=result + x; } return result; }

  • for文について

    以下のプログラムにおいて, for文の末尾にセミコロンがついているタイプ( for(...); ) のfor文の制御の流れは,セミコロンがついていないタイプ( for(...) ) と何が違うのでしょうか? for文の末尾にセミコロンがないタイプのものしか知らないため, セミコロンがつくことで流れに何が変化するか知りたいです. 御存知の方がいらしたら,教えてください. 【出力結果】 forの末尾にセミコロンがある 2100 forの末尾にセミコロンがない 700 /*+++++++ ソース ++++++++*/ #include <stdio.h> int main() {  int s_tb1[3] = {60,100,150};  int mg_tb[3] = {1,3,4};  int i,size=80,base=600,mode=1,ext=100;  for(i=0; size>s_tb1[i]; i++);   printf("%d\n", (base+mode*ext)*mg_tb[i] );  return(0); }

専門家に質問してみよう