第10講 for文以外の繰り返し(ループ)処理
第4話 合計の上限値を越えない等差数列の和

q
を実現するプログラム例
#include<iostream>
using namespace std;
int f1(int h,int j,int k);
int f2(int h,int j,int k);
int f3(int h,int j,int k);
long f4(int h,int j,int k);
void main(){
   int h,j,k,i,w; //hははじめの値(初項)、jは合計の上限値、kは変化の幅(公差)
   cout<<"はじめの値は?"<<endl;
   scanf("%d",&h);
   cout<<"合計の上限値は?"<<endl;
   scanf("%d",&j);
   cout<<"変化の幅?"<<endl;
   scanf("%d",&k);
   if(f1(h,j,k)>0){
     cout<<"1乗の和="<<f1(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
   if(f2(h,j,k)>0){
     cout<<"2乗の和="<<f2(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
   if(f3(h,j,k)>0){
     cout<<"3乗の和="<<f3(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
   if(f4(h,j,k)>0){
     cout<<"4乗の和="<<f4(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
}

int f1(int h,int j,int k){
   int i,w;
   i=h;
   w=0;
   while(1){
     w=w+i;
     if(w>j){
        w=w-i;
        break;
     }
     i=i+k;
   }
   return(w);
}

int f2(int h,int j,int k){
   int i,w;
   i=h;
   w=0;
   while(1){
     w=w+i*i;
     if(w>j){
        w=w-i*i;
        break;
     }
     i=i+k;
   }
   return(w);
}

int f3(int h,int j,int k){
   int i,w;
   i=h;
   w=0;
   while(1){
     w=w+i*i;
     if(w>j){
        w=w-i*i*i;
        break;
     }
     i=i+k;
   }
   return(w);
}

long f4(int h,int j,int k){
   int i;
   long w;
   i=h;
   w=0;
   while(1){
     w=w+i*i;
     if(w>j){
        w=w-i*i*i*i;
        break;
     }
     i=i+k;
   }
   return(w);
}
解説
どうです。皆さんうまくいきましたか。
うまくいかなかった方もいらっしゃるのではないでしょうか。
実は前話の課題をwhile文で実行するのは、かなり難しいのです。
私もうっかり最初は次にようにしてしまいました。
#include<iostream>
using namespace std;
int f1(int h,int j,int k);
int f2(int h,int j,int k);
int f3(int h,int j,int k);
long f4(int h,int j,int k);
void main(){
   int h,j,k,i,w; //hははじめの値(初項)、jは合計の上限値、kは変化の幅(公差)
   cout<<"はじめの値は?"<<endl;
   scanf("%d",&h);
   cout<<"合計の上限値は?"<<endl;
   scanf("%d",&j);
   cout<<"変化の幅?"<<endl;
   scanf("%d",&k);
   if(f1(h,j,k)>0){
     cout<<"1乗の和="<<f1(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
   if(f2(h,j,k)>0){
     cout<<"2乗の和="<<f2(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
   if(f3(h,j,k)>0){
     cout<<"3乗の和="<<f3(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
   if(f4(h,j,k)>0){
     cout<<"4乗の和="<<f4(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }

int f1(int h,int j,int k){
   int i,w;
   i=h;
   w=0;
   while(1){
     w=w+i;
     i=i+k;
     if(w>j)break;
   }
   return(w);
}

int f2(int h,int j,int k){
   int i,w;
   i=h;
   w=0;
   while(1){
     w=w+i*i;
     i=i+k;
     if(w>j)break;
   }
   return(w);
}

int f3(int h,int j,int k){
   int i,w;
   i=h;
   w=0;
   while(1){
     w=w+i*i*i;
     i=i+k;
     if(w>j)break;
   }
   return(w);
}

long f4(int h,int j,int k){
   int i;
   long w;
   i=h;
   w=0;
   while(1){
     w=w+i*i*i*i;
     i=i+k;
     if(w>j)break;
   }
   return(w);
}

ところがこれだと実行結果例は、
となり、すべてが合計上限値を超えてしまっています。
c
理由は、if(w>j)break;でループを抜ける判定するときすでに上限値を超えてしまっています。
そこで、if(w>j)break;をif(w=>j)break; と改良したらどうでしょうか。
x
確かに、1乗の和だけ条件を満たしました。
しかし、2乗以上ではすべて10を超えてしまいました。
理由は、1乗の場合は
1+2+3+4=10なので、if(w=>b)break;でたまたま条件に反せずループを抜け出しただけです。
2乗の場合は、
1の2乗+2の2乗=1+4=5<10なので、ループ処理が続きます。
次の
1の2乗+2の2乗+3の2乗=1+4+9=14でループを抜けることになりますが、
すでに上限値の10を超えてしまっています。
     w=w+i*i;
     i=i+k;
の処理をしてから、判定していることに問題があるのでしょうか。
もし、そうなら次のように改良すれば、問題は解決するはずです。
#include<iostream>
using namespace std;
int f1(int h,int j,int k);
int f2(int h,int j,int k);
int f3(int h,int j,int k);
long f4(int h,int j,int k);
void main(){
   int h,j,k,i,w; //hははじめの値(初項)、jは合計の上限値、kは変化の幅(公差)
   cout<<"はじめの値は?"<<endl;
   scanf("%d",&h);
   cout<<"合計の上限値は?"<<endl;
   scanf("%d",&j);
   cout<<"変化の幅?"<<endl;
   scanf("%d",&k);
   if(f1(h,j,k)>0){
     cout<<"1乗の和="<<f1(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
   if(f2(h,j,k)>0){
     cout<<"2乗の和="<<f2(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
   if(f3(h,j,k)>0){
     cout<<"3乗の和="<<f3(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
   if(f4(h,j,k)>0){
     cout<<"4乗の和="<<f4(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
}

int f1(int h,int j,int k){
   int i,w;
   i=h;
   w=0;
   while(1){
     if(w>=j)break;
     w=w+i;
     i=i+k;
   }
   return(w);
}

int f2(int h,int j,int k){
   int i,w;
   i=h;
   w=0;
   while(1){
     if(w>=j)break;
     w=w+i*i;
     i=i+k;
   }
   return(w);
}

int f3(int h,int j,int k){
   int i,w;
   i=h;
   w=0;
   while(1){
     if(w>=j)break;
     w=w+i*i*i;
     i=i+k;
   }
   return(w);
}

long f4(int h,int j,int k){
   int i;
   long w;
   i=h;
   w=0;
   while(1){
     if(w>=j)break;
     w=w+i*i*i*i;
     i=i+k;
   }
   return(w);
}
ところが実行結果はxで同じです。

なぜでしょうか。
     w=w+i*i;
     i=i+k;
の処理をする前にループを抜けているのに、
なぜうまくいかないのでしょうか。
理由は、簡単です。
if(w=>j)break; の判定が行われたとき、
2乗以降では上限値の10を超えてしまっているのです。
1の2乗+2の2乗=1+4=5 の次は、
1の2乗+2の2乗+3の2乗=1+4+9=14ですでに超えてしまっています。
1の2乗+2の2乗=1+4=5 のとき、
5<10でif(w=>b)break;の条件式を満たしませんから、
     w=w+i*i;
     i=i+k;
の処理は行われてしまうのです。
そして、その処理をした際に、
1の2乗+2の2乗+3の2乗=1+4+9=14で上限値の10を超えてしまうのです。
超えた後に、
   cout<<"2乗の和="<<f2(h,j,k)<<endl;
での表示ですから当然14が表示されてしまいます。
つまり、最後の処理
     w=w+i*i;
     i=i+k;
は余計だったのです。

以上の問題を解決するためには、
   while(1){
     w=w+i*i;
     if(w>j){
        w=w-i*i;
        break;
     }
     i=i+k;
   }
等としなければならないのです。
足したときに上限値を超えています。
最後の足し算が余計なわけですから、
差し引いてもとに戻してから終了しなければならないわけです。

また、
   if(f4(h,j,k)>0){
     cout<<"4乗の和="<<f4(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
等に?に方もいらっしゃると思います。
これは、はじめの値が3、上限値が20だとすると、
3の4乗で81ですから、はじめから上限値を超えているわけです。
解答例の
long f4(int h,int j,int k){
   int i;
   long w;
   i=h;
   w=0;
   while(1){
     w=w+i*i*i*i;
     i=i+k;
     if(w>j)break;
   }
   return(w);
}
だと0を返してきますので、
   if(f4(h,j,k)>0){
     cout<<"4乗の和="<<f4(h,j,k)<<endl;
   }
   else{
     cout<<"初項の段階で上限値を越えています。"<<endl;
   }
などとしています。



while文が前判定であるのに対して、
後判定を行う処理もあります。
それが、do...while文です。
do{
     ・
     ・
     ・
}while(条件式);

その際の注意は、while文では『}』で終わっているため『;』がいらないのに対して、
do...while文の場合は最後が『)』であるため『;』がいるということです。
;は文の終わりを示しますが、『}』でもC言語は文の終わりと見なしてくれます。
ですから、『}』で終わるときは『;』がいらないのです。
それ以外は、『;』は普通の文の『。』に相当するものなので必ず入れなければなりません。
プログラムをdo...while文で書き直してみましょう。


第3話へ 第5話へ


a

魔方陣 数独で学ぶ VBA 入門
数独のシンプルな解き方・簡単な解法の研究
VB講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 C++ 入門 基礎から応用まで第1部
eclipse java 入門
java 入門 サイト 基礎から応用まで
VC++ C言語 C++ 入門 初心者 基礎から応用まで
本サイトトップへ