whileループとforループの証明可能性


8

私にはこの先生がいます、彼はとても賢いです(時々、ハハ)彼は良いプログラマーがwhileループの代わりにforループを使用しようとすると言いました。彼がこの理由を挙げたのは、whileループは証明できるためです。たとえば、whileループで何が起こるかを完全に説明できるのに、ループではそれを行うことができないからですfor。彼はまた、NASAプログラマーがwhileループのみを使用していforて、これが原因でループを実行できないことについても述べています。

私はこれを理解するのにかなり苦労しています。両方のループについて、それらがどのように機能するかを詳細に説明できますか?両方のためにあなたはいつも何が起こるかを知っていますか?

誰かがwhileループを証明できる理由を私に説明できますか(そのため、for少なくとも場合によってはループよりも優れている可能性があります)。

編集:
多分彼は次のように言っていました:
2:すべてのループには上限が固定されている必要があります。チェックツールが、ループの反復回数の事前設定された上限を超えてはならないことを静的に証明することは、自明である必要があります。ループ境界が静的に証明できない場合、ルールは違反していると見なされます。

ただし、これでも、whileループとforループの違いについては何も言われていません。


17
あなたの先生は完全に間違っているか、あなたは彼が何とか言ったことを誤って報告しました。優先forするwhileというこの根拠は、単に意味がありません。あるかもしれませんが、これはそうではありません。
Kilian Foth、2015

7
私はキリアンに同意します。:for (init; test; step) { body }への簡単な脱糖があるように、違いがあるべきだとは意味がありません。while{init; while (test) { step; body }}

1
For(;;){cout << "彼らは実際にはそれほど異なっていない" << endl;}。最大の違いは、forループを使用すると、変数(i)をループのスコープに簡単に保持できることです。
Nathan Cooper、

2
逆に@MikeNakis。貨物耕作者は質問をするのではなく、神話を永続させるだけです。おそらく、「ルールを守らない」ことで他人を罰することさえあるでしょう。
sehe 2015

2
@MikeNakis先生のしつこさを評価するのに十分な情報があるかどうかわかりません。
sehe

回答:


13

一言で言えばどのようなあなたの先生は、おそらく意味することの意味があるということwhileの意味は、一方で、かなりのほとんどの言語でも同じであるfor(以下の説明を参照)を大幅に変更されることがあります。したがって、抽象言語に依存しない証明はを使用した方が信頼性が高くwhileなりforますが、ループを使用した証明forは多くの言語のループのセマンティクスと一致しない可能性があることに注意する必要があります。

あなたの質問は十分正確ではありません(それはあなたのせいではないかもしれません)。

重要なのは、afaikには、公式でISOでサポートされている標準、またはその他の方法で公式に受け入れられているforand whileループの参照定義がないということ です。定義はプログラミング言語に依存します。

したがって、それぞれが何を実行できるかを正確に定義する前に、それらの同等性に関する一般的な説明を行うことはできません。より正確に言えば、それは他の回答で使用される主要な議論の1つであるためです(そして、この議論は以下で役立つでしょう)。

forand whileループの相互翻訳について

要約それはプログラミング言語に依存しますが、無限ループとそれを抜け出す方法を1つ持つことができる限り、常に可能です。

しかし、特定のプログラミング言語に対してそのようなステートメントを作成することができ、答えは言語の機能に依存します。

これはまた、一般的な証明はなく、プログラミング言語ごとに1つしかないことも意味します。

一般的に当てはまることの1つは、whileループがforループの終了条件テストを実行し、ループに入る前に割り当てを使用して制御変数の初期化を実行し、増分を実行できるため、ループがループをwhile模倣forできることですループ本体の終わりにあるので、

for i from 1 by 2 to 10 do { xxx }

なる

i=1
while i≤11 do { xxx; i←i+2 }

これは多かれ少なかれほとんどの言語で機能しますが、見た目ほど明白ではなく、心配する必要のある「詳細」がたくさんあるかもしれません。

たとえば、多くの言語では、forループは3つの引数(初期値、増分、および最終値)を厳密な引数として評価し、ループに入る前に一度評価されますが、他の人はサンク引数として各ターンで再評価されるか、またはおそらく最初に必要なときにのみ評価される遅延引数として。

もう1つのポイントは、インクリメント変数が forループに対してローカルであるか、ループが出現する関数のローカル変数である必要があることです。

そのような問題に応じて、a forからaへの変換はwhile大きく異なりますが、通常はそれを実現することが可能です。

同じことが逆に当てはまり、whileaがforループに変換されます。

最初の問題は、whileループが常に各ターンで終了条件を再評価することです。ただし、一部のforループは、制御変数とループエントリで計算された固定値との比較を除いて、各ターンで再評価される条件を提供しません。次に、任意の条件でループから抜け出す他の手段がない限り、変換は不可能です。

これは、さまざまなデバイスで実現可能です。通常、条件をテストする条件ステートメントで始まり、次に、ループ終了ステートメント、戻りステートメント(ループを関数にカプセル化した後)、gotoステートメントによって、ジャンプアウトが実装されます。または例外の発生。

言い換えれば、それは再び言語に、そしておそらく言語の微妙な特徴に非常に依存しています。

これは、@ milleniumbugによって回答されたように、forloppは本質的にwhileループとインクリメントされた制御変数の追加の部分であるため、言語Cでの相互翻訳は簡単です。

しかし、これは必ずしも他の言語に当てはまるわけではなく、おそらく同じようには当てはまりません。

そうは言っても、必要なのは1つの無限ループだけなので、プログラミング言語は通常、これらのループの1つだけでチューリングパワーを備えているはずです。したがって、永遠にループする方法があり、停止する可能性がある限り、他の構成要素を模倣できると確信できますが、必ずしも簡単ではありません。

証明について

要約:(言語の奇妙な特徴がない限り)証明はどちらか一方の方がかなり難しいと主張する理由は私にはわかりません。

おそらく誤解があるか、先生が他のことを考えていました。

正式なセマンティクスは、プログラミング言語で定義されたさまざまな種類のループに対して定義でき、プロパティの証明に使用できます。

言語によっては、プログラムに関する正式な証明の実施が場合によってはより複雑になる場合があります。しかし、それは言語に依存します。

ある構成の方が他の構成よりも証明が大幅に困難になる理由は想像できません。forそれは、Cのように、で行われている全て提供できるので、ループはより複雑かもしれwhileプラス他のものを。しかし、それをで行った場合while、他の形式でエキストラを追加する必要があります。

単一の無限ループの可能性がある限り、相互翻訳可能性の正式な一般論を使用できます。ただし、関係する構造は証明で処理したくないものであり、少なくとも実際には不公平な声明であるため、これを行うことは控えます。

しかし、上記の議論に続いて、翻訳可能性の難しさはfor、言語間のループの大きな変動性に起因することがわかりました。したがって、おそらく正しい答えである次の結論:

先生の発言を理解する1つの可能性は、whileループのセマンティクスはすべてのプログラミング言語でほとんど同じである一方で、forループの構文とセマンティクスは言語によって大幅に異なる可能性があることです。したがって、言語に依存しないセマンティクスを持つwhileループで一般的な「抽象的な」証明を作成することは可能ですがforこれは構文やセマンティクスが言語から言語に大きく変化するループでは不可能です。しかし、これは、両方のセマンティクスが正確に定義されている場合、特定の言語内では適用されません。

私の最善の提案は、先生が正確に何を意味しているか、先生に例を示すことができるかどうかを先生に尋ねることです。誤解や誤解はよくある出来事です。


1
@VincentAdvocaatさて、このサイトはすべてのユーザー向けであり、質問の元のポスターだけではありません。それが私がやった理由です。また、モデレーターが不適切な場合はそれを停止するように、自分の回答にフラグを付けました。実際、それは興味深い質問でした、そして私の結論に達するのにしばらく時間がかかりました...それが正しいものであることを望んでいます。見つけたら教えてください。
バブー2015

私はあなたが1時間前に行った編集に気づいただけで、ここにあなたの答えにあなたが述べた内容を追加しました。これは確かに私の質問に対する最良の答えです。ありがとうございました。モデレーターの注意が関係していることは、複数のSEサイト間で複製を作成することのほうが私の責任です。だから私はこの答えを削除する理由はないと思います、もし何か詳細が必要な場合は、私が尋ねた2番目の質問でなければなりませんが、あなたの答えはよく定式化されており、ここで行われた声明を詳細に説明しているので、私は賢明ではないと思いますどちらかを削除します。この質問に情報を追加しない限り。
Vincent

1
私にはわからない、奇妙なことが起こる、人々がこの理由を説明しないときはいつも楽しい。
Vincent

3
再び起こった:1アップ+ 1ダウン。気になるのは、自分よりサイトを傷つけていることです。私は人々を助ける完全な答えを書こうとします。それが誤りである場合、私に訂正する機会を与えるためにコメントすることは賢明でしょう。それが他の理由である場合は、サイトの費用で、役に立つかもしれない回答の魅力を減らすだけです。拡張された回答で置き換えること、または最後に免責事項を削除することは、それと何か関係があるのではないかと思っています。しかし、モデレーターは状況に問題がないように見えました。
バブー2015

1
モデレーターとして私はあなたの答えが好きで、私はそれを読むことから何かを学びました。良い答えです
maple_shaft

12

C言語では、すべてのforループを同等のwhileループに書き換えたり、その逆を行うことができます。

while -> for 変換:

リライト

while(condition) { instructions; }

for(; condition; ) { instructions; }

for -> while 変換:

これは、特にcontinueループ内にステートメントがある場合、少し複雑になります。

リライト:

for(init; condition; next) { instructions; }

に:

{
    init;
    while(condition)
    {
        instructions;
    next_label:
        next;
    }
}

ただし、すべてのcontinue;ステートメントをgoto next_label;ステートメントに置き換えます。conditionがnull命令の場合、それをに置き換えますtrue

ご覧のように、C言語では、どちらのループも(それが何であれ)どちらも「証明可能」ではありません。ループの1つがそうであったとしても、別のループに関して書き換えることができるためです。

現在、このwhile <-> for同等性が存在しない他の言語が存在します。たとえば、Pascalでは、forループについてより多くのことを想定できます。つまり、forループを書くときにすべての概念を表現することはできませんが、コードの流れについてより多くのことを証明できます。

for i:=1 to n do
    instructions;

ここでnは、ループの開始時にが保存されるため、変更がn反復回数に影響を与えないようiになり、ループの本体で変更することはできません。これは、このループが最終的に終了することを自明に証明できることを意味します(n有限であるため、変更できませんi)。


一部の「for」ループを「while」ループとして書き換えると、コードの重複、フラグの追加、またはの追加が必要になりますgoto。フラグを追加すると、他のすべてのループは、「戻る」まで実行される関数の周りの単一の「while(1)...」を使用してエミュレートできます。「goto」を追加すると、それを使用して他のすべてのループをエミュレートできます。
スーパーキャット2016

私のポイントを証明してくれてありがとう。コードフラグメントAをコピーして貼り付けても、それについて論理的に説明する能力は変わりません。
ミレニアムバグ2016

確かに、コピー/貼り付けはコードについて推論する能力を変更しませんが、優れたプログラミング言語の設計目標の1つは最小化する必要があるため、 "for"を余分な言語構造と見なさないことが重要な理由です。必要性のコピー/貼り付けのために。
スーパーキャット2016

7

ではフロイド・ホーア論理、コンピュータプログラムの正しさについての推論のための最も一般的な形式的なシステムがあり、しばらくルールが

つまり、ガード節(の括弧内の式while())、バリアント関数(ループが実行されるたびに単調に減少し、常に正になることが示される離散値を持つ式)、およびループ不変式がある場合(ループが実行されるたびに前後に常に真となる論理ステートメント)、whileループが終了することを証明できます(バリアント関数が減少し続けることができないため)、最終的にガード節が偽になり、ループになることを証明できます不変であること。

Floyd-Hoareロジックには、forループのルールや、実際の言語が持つ可能性のある構造はありません。

ただし、他の回答で説明されているように、forループは常にwhileループの観点から記述できます。それは彼らが推論できることを意味し、それはちょうどもう少し多くの仕事が必要です。

先生が大学でコースを持っている場合、そのプログラムの正当性を証明する必要があり、おそらくwhileループのみを使用してプログラムを作成しました。私はそうしました。そして、ガードやバリアント関数、ループ不変量について考えることに慣れると、それらは非常に自然に見えます。whileループを使いすぎるのはCSの卒業生によく見られる習慣ですが、私はプロの開発者としての最初の数か月でそれをやめることを学ばなければなりませんでした。

どこかで、先生はこれをすべて「優れたプログラマーがwhileループを使用する」と覚えていましたが、実際に起こるのは、「CSの卒業生の中には、正しさを証明する習慣を実際のプログラミングの習慣に変える」というようなものです。


これは、別の見方に基づいていますが、私自身の評価とかなり一致しているようです。Floyd-Hoareロジックには、forループを検討する理由がありませんでした。このループは、定義が固定されておらず、複雑であり、正式には必要ありません。
バブー2015

3

実際、ある意味では、正反対のことが当てはまります。

for-loops のみの言語は、チューリング完全ではなく、すべてのチューリング計算可能関数ではなく、プリミティブ再帰関数のみを計算できます。for-loops のみの言語でのすべての計算は常に終了するので、停止問題とそれに基づく他のすべての決定可能性問題は単に発生しないので、プログラムの静的プロパティを、while-ループ。

自然数、単一の変数、およびwhile-loops のみを持つ言語であるOTOH チューリング完全であるため、最も単純なプロパティでさえ決定することはできません。このプログラムは結果を返しますか?


1
- forのみの言語はwhile、ループが終了することを想定していない反復中にループ変数をデクリメントすることで(言語がそれを想定している場合)、同等の動作を生成できます。(例for n in 1 to 2 { if condition then n := n-1 }
Blrfl 2015

もちろん、手元の言語での定義に応じて、forループを永久にループさせる方法はたくさんあります。そして、チューリング完全性のためには、1つの無限ループで十分です。
バブー2015

@babou:forループの最も一般的な解釈は、有限の範囲またはコレクションを反復するループです。もちろん、多くの言語では、forループをハックしてwhileループのように動作させることができますが、それはJörgが意図していたことではないと思います。
ジョルジオ

0

私は実際には違いはないと言いたいです。あなたの質問は無関係です。教師が、いいえのときにwhileループを使用するつもりだったかもしれません。多くの場合、whileループを使用してnoの数字を抽出する必要があります。ユーザーがいいえを入力したとき。長さは任意です。技術的に言えば、for&whileループの類似点は、両方がエントリ制御ループであり、(test-expression / condition)がループ本体に入る前に評価されるということです。これが、while&do-whileループの違いです。


-1

それはおそらく、今日の規範までに、ループが広く悪用され、誤用され、特に条件が変更された初期のCプログラミングに起因する可能性があります。プログラマーが特定のプログラミングスタイルの影響を理解し始めると、ループ条件の乱用と誤用は支持されなくなり、ステートメントは(おそらく)かつては有効でしたが、もはや真実ではなくなりました。

言語の定義と構文だけを見て、それがどのように使用されたかを無視した場合、ステートメントはまったく真実ではありません。

しかし、声明自体は、それ、その歴史、そしてなぜそれがもはや真実であると考えられていないのかを理解したい人には、貴重な教訓を提供します。-学習、間違い、そしてそれらを繰り返すことについての表現は何ですか。


-10

あなたの先生は正しいです!

理由は次のとおりですC

for (int x = 1 ; x < 20 ; x++ ) {
   x = x + 9;
}

条件変数が改ざんされていないことは保証できません!


2
どのようにメイクんwhileループは、ここより良い運賃?
ミレニアムバグ2015

7
そうそう?一方、whileループを使用すると、条件変数が改ざんされていないことを実際に保証できますか?実際、条件変数を改ざんすることがwhileループから抜け出す唯一の方法です!私は通常、投票に反対することは控えていますが、この答えのために、例外を設けます。
Mike Nakis、2015

Jamesは、これがwhileループの問題ではない理由を詳しく説明していただけませんか。何かに疑問があるかもしれませんが、whileループの場合の反証の証拠については人々が同意しないようです
Vincent

1
私はあなたがwhileループでそれを言うと思います@VincentAdvocaat 期待 forループあなたはそれが唯一のループ構造自体のためのステップ部に変更することを期待するのに対し、条件変数は、何らかの方法で改ざんされます。この最小の驚きの原則は、プログラミングで多くの人が理解するよりも重要です。
gbjbaanb 2015

3
@gbjbaanbは真実ですが、質問に関する限り、それは最小の驚きの原則から証明可能性まではかなりかけ離れています。
Mike Nakis、2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.