0

ユーザー入力を受け取るプログラムを C 言語で作成したいのですが、ループのロジックが理解できません。

for ( c = 2 ; c <= n - 1 ; c++ )

プログラム コードを以下に示します。

#include<stdio.h>
#include<conio.h>

void main()
{
   int n, c;

   printf("Enter a number to check if it is prime\n");
   scanf("%d", &n);

   for ( c = 2 ; c <= n - 1 ; c++ )
   {
      if ( n % c == 0 )
      {
         printf("%d is not prime.\n", n);
         break;
      }
   }
   if ( c == n )
      printf("%d is prime.\n", n);

   getch();
}

私は for ループのステートメントを終了する for ループを使用しましたn - 1。私が入力を与えると、11それは最終的に11 - 1 = 10どのように論理を放棄するの if(c == n) { printf("%d", n);でしょうか?

4

4 に答える 4

6

私が入力を与えると、11それは最終的に11 - 1 = 10どのように論理を放棄するの if(c == n) { printf("%d", n);でしょうか?

for ループの条件を正しく理解するようになりました。

for ( c = 2 ; c <= n - 1 ; c++ )
              ^^^^^^^^^^^^
              2 <= 11 - 1  -> True   // {for block executes }
              3 <= 11 - 1  -> True   // {for block executes }
                 :
                 :
              9 <= 11 - 1  -> True   // {for block executes }
              10 <= 11 - 1  -> True  // {for block executes }
              11 <= 11 - 1  -> False  breaks //{And Now for block NOT executes}

if (c == n)
    ^^^^^^
   11 == 11 -> True  // {if block executes} 

for ループ条件 に従って、 value が と等しくなるとc <= n - 1ループが中断されます。したがって、is equals to ループ条件が true の場合、各反復で(インクリメントを使用して)が1 ずつインクリメントされると、条件が false になり、ループが中断されます。cnn11c = 2c = 10cc++c11nc <= n - 1

if 条件 (for ループの後) のc値を と比較しnます。あれは:

if ( c == n )
//   11 == 11  that is true

for n=11となり、and c= 11if condition が true と評価されprintf()、if が実行される場合に関連付けられます。


c = nまた、for ループは for が素数の場合にのみ終了することを理解することも重要ですnが、 が素数でないと仮定すると、for ループ内のネストされたブロック内の ステートメントにより、 for ループは以下の値でn中断します。cn - 1break;if

for( c = 2; c <= n - 1; c++ ) 
{
  if(n % c == 0)<=="for Non-prime `n`, if condition will be true for some `c < n - 1`"
  {  ^^^^^^^^^^^ True 
     printf("%d is not prime.\n", n);
     break; <== "move control outside for-loop"
  }  //      | 
}    //      |
// <---------+ // if break; executes control moves here with c < n - 1
if (c == n)<== "this condition will evaluates FALSE"  
   ^^^^^^^^ False

たとえば、if n = 8then の for ループの最初の反復で、値c = 2if 条件が== = Trueif(n % c == 0)として評価され、 ifブロック内のステートメントが制御を for ループの外に移動します (図に示すように)。 if(8 % 2 == 0)if( 0 == 0)break;

この時間の for ループは条件により終了していませんが、外側の for ループの値よりも小さいため c <= n - 1にブレーキがかけられているため 、False と評価されます。if(n % c == 0)cnif (c == n)

于 2013-10-16T13:37:04.493 に答える
2

for ループは、ステートメントにヒットc = 2する以外はループします。もしそうなら、それはループから飛び出します。あなたが決して壊れないなら、あなたは実際にループの後になります。c = n - 1breakcn

そして、これがその理由です。ループは次のように機能します。

  1. forループを初期化するc = 2
  2. 条件をチェックする(c <= n - 1) true の場合: ループ本体を実行 false の場合: ループを飛び越える
  3. c1ずつ増やす
  4. 2へ。

例: あなたnが 3 だとします。

  1. c2に設定c == 2します。n == 3
  2. 2 <= 3 - 1は真なので、ループ本体が実行されます
  3. c == 3ここで、c を 1 ずつインクリメントします。n == 3
  4. 説明の 2. に戻ります
  5. 3 <= 3 - 1は false なので、今はループ本体を実行せず、ループから飛び出します
  6. ループを抜けた後c == 3などn == 3c == n

したがって、break ステートメントにヒットしない場合は、ループの後cと同じになります。n が素数でない場合n、break ステートメントにヒットします。中断すると、少なくとも1 つのインクリメントが失われるため、ループの後になります。現在は false と評価され、if ステートメント本体は実行されません。cc < nc == nif ( c == n )

今すぐにif ( n%c == 0 )n%cnmoduloを意味するので、 によるcの除算の余りです。この剰余が 0 の場合、は の整数除数です。したがって、ループでは、1 より大きく より小さい除数をテストしています。nccnnn

n1 とそれ自身以外の約数がある場合、n素数にはなりません。したがって、0 に等しいものをヒットするcと素数にはなりません。1 < c < nn%cn

ヒント: より大きい約数をテストする必要はありません√n

于 2013-10-16T13:17:28.640 に答える
1

あなたの仮定は間違っていcます。デバッガーを使用してプログラムをステップ実行すると、ループの最後に for が表示されるはずです。n - 1n == 11c == 11

早期に中断しない場合、ループ本体が実際に最後に実行されるのc == n - 1c、その後インクリメントされ、ループ不変テストが失敗するため、 loop の後c == nです。

于 2013-10-16T13:35:25.903 に答える
0

数が素数であると言うとき、それが何を意味するか考えてみてください。数 p が素数であるのは、 がすべてn>1, n<p、残りr = 0が の場合ですp/n = r

したがって、このループは各値 (c) 範囲を実行[2..p-1]し、残りをテストします。

int isprime = 1; //use a flag to indicate prime, assume prime until proven otherwise
for ( c = 2 ; //initialize c=2, the first value in the range [2..p-1]
      c <= n - 1 ; //check whether c is still in the range [2..p-1]
      c++ ) //increment c to the next value in the range [2..p-1]
{
    if ( n % c == 0 ) //modulo '%' is the remainder of the integer division
    {
        isprime = 0;
        break;
    }
}
printf("%d %s prime.\n", n, isprime?"is":"is not");

ループ カウンターの副作用をチェックして数値が素数であることをテストするのではなく、ループの前にフラグを設定し、最後に素数の決定としてそれをテストしてみませんか? その結果、壊れにくく、エラーが発生しにくく、より明確なコードになります。

約半分の作業を節約したいですか? をテストするn%2と、 のような数 k は存在しないことがわかりk*2=nますね。範囲[2..p/2]を確認し、ループを次のように変更します。

for( c = 2; c <= n/2; c++ )

それよりも小さい数を考えることができますn/2か?

複数の素数を見つけるための興味深いアルゴリズムは、エラストステネスのふるいです

于 2013-10-17T17:13:30.670 に答える