Provabilitas while loop vs for loop


8

Saya memiliki guru ini, dia cukup pintar (kadang-kadang, haha) katanya programmer yang baik mencoba menggunakan whileloop, bukan forloop. alasan yang dia berikan untuk ini adalah karena whileloop dapat dibuktikan, seperti pada, seseorang dapat sepenuhnya menjelaskan apa yang terjadi dalam satu whileloop sedangkan Anda tidak dapat melakukan itu untuk satu forloop. dia juga mengatakan sesuatu tentang programmer NASA hanya menggunakan whileloop dan tidak diizinkan melakukan forloop karena ini.

Saya mengalami kesulitan memahami hal ini, karena kedua loop dapat menjelaskan bagaimana mereka bekerja secara detail, bukan? untuk keduanya Anda akan selalu tahu apa yang akan terjadi?

Dapatkah seseorang menjelaskan kepada saya mengapa whileloop dapat dibuktikan (Dan karena itu, mungkin lebih baik daripada forloop, dalam beberapa kasus setidaknya).

EDIT:
mungkin dia merujuk ke:
2: Semua loop harus memiliki batas atas yang tetap. Itu harus sepele mungkin untuk alat pengecekan untuk membuktikan secara statis bahwa batas atas yang ditentukan pada jumlah iterasi loop tidak dapat dilampaui. Jika loop-terikat tidak dapat dibuktikan secara statis, aturan dianggap dilanggar.

Meskipun ini masih tidak mengatakan apa-apa tentang perbedaan antara while dan for loop.


17
Guru Anda salah total, atau Anda salah melaporkan apa yang dikatakannya. Alasan untuk lebih memilih fordaripada whilesekadar tidak masuk akal. Mungkin ada satu, tapi ini bukan.
Kilian Foth

7
Saya setuju dengan Kilian. Tidak masuk akal bahwa harus ada perbedaan, seperti for (init; test; step) { body }memiliki desugaring sepele untuk while: {init; while (test) { step; body }}.

1
Untuk (;;) {cout << "mereka benar-benar tidak jauh berbeda" << endl;}. Perbedaan terbesar adalah bahwa untuk loop, Anda dapat dengan mudah menyimpan variabel (i) di lingkup loop.
Nathan Cooper

2
@ MikeNakis sebaliknya. Seorang culter kargo tidak akan mengajukan pertanyaan, hanya mengabadikan mitos. Mungkin bahkan menghukum orang lain karena tidak "mematuhi aturan".
lihat

2
@ MikeNakis Saya tidak tahu apakah kami memiliki informasi yang cukup untuk menilai kemampuan guru.
lihat

Jawaban:


13

Singkatnya : Apa yang mungkin dimaksudkan oleh guru Anda adalah bahwa semantik whilehampir sama di sebagian besar bahasa, sedangkan semantik formungkin berubah banyak (lihat diskusi di bawah). Oleh karena itu, bukti independen bahasa abstrak lebih dapat diandalkan dengan a while, tetapi orang harus berhati-hati bahwa bukti dengan forloop mungkin tidak cocok dengan semantik forloop dalam banyak bahasa.

Pertanyaan Anda tidak cukup tepat (meskipun itu mungkin bukan salah Anda).

Intinya adalah bahwa, afaik, tidak ada standar, standar yang didukung ISO, atau definisi fordan whileloop referensi yang diterima secara resmi . Definisi ini tergantung pada bahasa pemrograman.

Karenanya Anda tidak dapat membuat pernyataan umum apa pun tentang kesetaraannya sebelum Anda menentukan dengan tepat apa yang dapat dilakukan masing-masing. Saya mengemukakan hal itu dengan lebih tepat, karena itu adalah salah satu argumen utama yang digunakan dalam jawaban lain (dan diskusi akan bermanfaat dalam apa yang berikut).

Pada intertranslatability fordan whileloop

Ringkasan : itu tergantung pada bahasa pemrograman, tetapi selalu mungkin selama Anda dapat memiliki satu loop tak terbatas dan cara untuk keluar darinya.

Tetapi Anda dapat membuat pernyataan seperti itu untuk bahasa pemrograman tertentu, dan jawabannya akan tergantung pada fitur untuk bahasa tersebut.

Itu juga berarti bahwa tidak ada bukti umum, tetapi hanya satu untuk setiap bahasa pemrograman.

Satu hal yang secara umum benar adalah bahwa whileloop umumnya dapat meniru forloop, karena loop sementara dapat melakukan pengujian kondisi keluar dari loop, melakukan inisialisasi variabel kontrol dengan tugas sebelum memasukkan loop, dan melakukan penambahan pada akhir loop body, sehingga

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

menjadi

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

Ini kurang lebih berfungsi untuk sebagian besar bahasa, tetapi tidak sejelas kelihatannya, dan mungkin ada banyak "detail" yang perlu dikhawatirkan.

Misalnya, dalam banyak bahasa, forloop mengevaluasinya 3 argumen (nilai awal, kenaikan, dan nilai akhir) sebagai argumen yang ketat , dievaluasi satu kali sebelum memasukkan loop, sementara yang lain akan menggunakan argumen thunk untuk dievaluasi kembali pada setiap belokan, atau mungkin sebagai argumen malas untuk dievaluasi hanya ketika pertama kali dibutuhkan.

Poin lain mungkin bahwa variabel kenaikan mungkin lokal ke forloop, atau harus variabel lokal dari fungsi tempat loop muncul.

Bergantung pada masalah-masalah seperti itu, terjemahan a forke a whiledapat sangat bervariasi, meskipun biasanya mungkin untuk mencapainya.

Hal yang sama berlaku untuk yang sebaliknya, menerjemahkan a whileke dalam satu forlingkaran.

Masalah pertama adalah bahwa whileloop akan selalu mengevaluasi kembali kondisi keluar di setiap belokan. Tetapi beberapa forloop tidak menyediakan kondisi yang dievaluasi ulang pada setiap belokan, selain perbandingan variabel kontrol dengan beberapa nilai tetap yang dihitung pada entri loop. Maka terjemahan tidak mungkin kecuali ada cara lain untuk melompat keluar dari loop pada beberapa kondisi yang sewenang-wenang.

Itu dapat dicapai dengan berbagai perangkat, biasanya dimulai dengan pernyataan kondisional menguji kondisi, diikuti dengan lompatan yang diimplementasikan, sebagaimana tersedia, dengan pernyataan keluar loop, pernyataan kembali (setelah merangkum loop dalam suatu fungsi), pernyataan goto atau peningkatan pengecualian.

Dengan kata lain, sekali lagi sangat tergantung pada bahasa, dan mungkin pada fitur bahasa yang halus.

Ini mengatakan, seperti dijawab oleh @milleniumbug , intertranslation mudah dalam bahasa C, karena forlopp pada dasarnya adalah sebuah whileloop ditambah beberapa tambahan untuk variabel kontrol yang ditambahkan.

Tetapi ini tidak selalu berlaku untuk bahasa lain, dan kemungkinan besar tidak dengan cara yang sama.

Ini dikatakan, bahasa pemrograman biasanya memiliki kekuatan Turing dengan hanya satu dari loop ini, karena semua yang Anda butuhkan untuk itu adalah satu loop tak terbatas. Jadi, selama Anda memiliki beberapa cara pengulangan untuk selamanya, dan mungkin memutuskan untuk berhenti, Anda cukup yakin Anda dapat meniru konstruksi lain ... tetapi tidak harus dengan mudah.

Mengenai bukti

Ringkasan : Tidak ada alasan bagi saya untuk menyatakan bahwa bukti harus secara signifikan lebih sulit dengan satu atau yang lain (kecuali beberapa fitur aneh dari bahasa).

Mungkin ada kesalahpahaman, atau guru Anda memikirkan sesuatu yang lain.

Semantik formal dapat didefinisikan untuk berbagai jenis loop yang didefinisikan dalam bahasa pemrograman, dan kemudian digunakan untuk membuktikan properti.

Mungkin, sekali lagi tergantung pada bahasa, bahwa melakukan bukti formal mengenai program mungkin lebih kompleks dalam beberapa kasus. Tetapi itu tergantung pada bahasanya.

Saya tidak bisa membayangkan alasan mengapa bukti harus jauh lebih sulit dengan satu konstruksi lebih dari yang lain. The forLoop mungkin lebih kompleks karena dapat menawarkan, seperti di C, semua yang dilakukan dengan whileditambah hal-hal lain. Tetapi jika Anda melakukannya dengan while, Anda harus menambahkan ekstra dalam beberapa bentuk lain.

Saya bisa menggunakan argumen umum formal tentang intertranslatabilitas, selama ada kemungkinan untuk satu loop tak terbatas. Namun saya akan menahan diri untuk tidak melakukan itu, karena konstruksi yang terlibat bukanlah sesuatu yang ingin Anda tangani dalam sebuah bukti, dan itu jelas merupakan pernyataan yang tidak adil, setidaknya dalam praktik.

Namun, setelah diskusi di atas, kita telah melihat bahwa kesulitan untuk transtranslabilitas berasal dari variabilitas besar forloop dari bahasa ke bahasa. Maka kesimpulan berikut yang mungkin merupakan jawaban yang tepat:

Satu kemungkinan untuk memahami pernyataan guru Anda adalah bahwa semantik whileloop hampir sama di semua bahasa pemrograman, sedangkan sintaks dan semantik forloop dapat bervariasi secara signifikan dari bahasa ke bahasa. Oleh karena itu, dimungkinkan untuk membuat bukti "abstrak" umum dengan whileloop yang memiliki semantik independen bahasa sampai tingkat yang baik, sementara ini tidak mungkin untuk forloop yang memiliki sintaks dan semantik berubah terlalu banyak dari bahasa ke bahasa. Tetapi ini tidak berlaku dalam bahasa tertentu, ketika semantik keduanya didefinisikan secara tepat.

Saran terbaik saya adalah Anda harus bertanya kepada guru Anda apa yang ia maksudkan dengan tepat, dan apakah ia dapat memberi Anda contoh. Misphrasing atau kesalahpahaman adalah peristiwa umum.


1
@VincentAdvocaat Ya, situs ini untuk semua pengguna, tidak hanya Poster Asli dari pertanyaan. Itu sebabnya saya melakukannya. Saya juga menandai jawaban saya sendiri untuk moderator untuk menghentikannya jika tidak tepat. Sebenarnya itu adalah pertanyaan yang menarik, dan butuh beberapa waktu untuk mencapai kesimpulan saya ... berharap itu yang benar. Beri tahu kami jika Anda mengetahuinya.
babou

Saya baru saja melihat hasil edit yang Anda buat satu jam yang lalu menambahkan apa yang Anda nyatakan dalam jawaban Anda di sini, ini memang jawaban terbaik untuk pertanyaan saya dan saya berterima kasih untuk itu. Yang menjadi perhatian moderator, lebih merupakan kesalahan saya untuk membuat duplikat di antara banyak situs SE Jadi untuk itu saya tidak melihat alasan untuk menghapus jawaban ini, jika ada sesuatu yang harus ditangguhkan itu harus menjadi pertanyaan ke-2 yang saya tanyakan, tetapi karena jawaban Anda diformulasikan dengan baik dan menjelaskan pernyataan yang dibuat di sini secara mendalam saya tidak berpikir itu bijaksana untuk menghapus salah satu. kecuali Anda menambahkan informasi ke pertanyaan ini.
Vincent

1
Saya tidak tahu, hal-hal aneh terjadi, selalu menyenangkan ketika orang tidak menjelaskan alasannya.
Vincent

3
Terjadi lagi: 1 naik +1 turun. Yang menggangguku adalah bahwa itu lebih merusak situs daripada diriku. Saya mencoba menulis jawaban lengkap yang membantu orang. Jika itu salah, akan lebih bijaksana untuk berkomentar untuk memberi saya kesempatan untuk memperbaiki. Jika itu adalah alasan lain, itu hanya mengurangi daya tarik jawaban yang mungkin berguna, dengan biaya situs. Saya bertanya-tanya apakah mengganti dengan jawaban yang diperluas, atau menghapus disclaimer pada akhirnya, ada hubungannya dengan itu. Tetapi moderator tampak baik-baik saja dengan situasinya.
babou

1
Sebagai moderator, saya menyukai jawaban Anda dan saya belajar sesuatu dari membacanya. Ini adalah jawaban yang bagus
maple_shaft

12

Dalam bahasa C Anda dapat menulis ulang setiap forloop ke loop yang setara whiledan sebaliknya.

while -> for transformasi:

Menulis kembali

while(condition) { instructions; }

untuk

for(; condition; ) { instructions; }

for -> while transformasi:

Ini sedikit lebih rumit, terutama jika Anda memiliki continuepernyataan di loop Anda.

Menulis kembali:

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

untuk:

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

tetapi ganti setiap continue;pernyataan dengan goto next_label;pernyataan. Jika conditionini adalah instruksi nol, gantikan dengan true.

Seperti yang Anda lihat, dalam bahasa C tidak ada yang lebih "dapat dibuktikan" (apa pun artinya) daripada yang lain, karena bahkan jika salah satu loop itu, Anda bisa menulis ulang dalam hal loop lain.

Sekarang, ada bahasa lain di mana while <-> forkesetaraan ini tidak ada. Misalnya, dalam Pascal, Anda dapat mengasumsikan lebih banyak tentang forloop. Ini berarti bahwa Anda tidak dapat mengekspresikan setiap konsep saat menulis satu forlingkaran, tetapi Anda dapat membuktikan lebih banyak tentang aliran kode:

for i:=1 to n do
    instructions;

Di sini, ndisimpan di awal loop, jadi perubahan untuk ntidak membuat pengaruh pada jumlah iterasi, dan Anda tidak dapat memodifikasi idalam tubuh loop. Ini berarti Anda dapat dengan mudah membuktikan bahwa loop ini pada akhirnya akan berakhir (seperti nyang terbatas, dan Anda tidak dapat memodifikasi i).


Menulis ulang beberapa "untuk" loop sebagai "while" loop akan membutuhkan duplikasi kode, menambahkan bendera, atau menambahkan goto. Jika seseorang menambahkan flag, semua loop lain dapat ditiru menggunakan satu "while (1) ..." di sekitar fungsi yang berjalan hingga "kembali"; jika seseorang menambahkan "goto", semua loop lain dapat ditiru menggunakan itu.
supercat

Terima kasih telah membuktikan pendapat saya. Menyalin-menempelkan fragmen kode A tidak mengubah kemampuan saya untuk mempertimbangkannya.
milleniumbug

Memang, salin / tempel tidak mengubah kemampuan seseorang untuk berpikir tentang kode, tetapi itu adalah IMHO alasan penting untuk tidak menganggap "untuk" sebagai konstruksi bahasa yang berlebihan, karena salah satu tujuan desain bahasa pemrograman yang baik adalah untuk meminimalkan yang perlu untuk copy / paste.
supercat

7

Dalam logika Floyd-Hoare , sistem formal paling umum untuk alasan tentang kebenaran program komputer, ada aturan sementara .

Dalam kata-kata, jika Anda memiliki klausa penjaga (ekspresi dalam tanda kurung dalam while()), fungsi varian (ekspresi dengan nilai diskrit yang dapat ditunjukkan berkurang secara monoton setiap kali loop berjalan, dan selalu menjadi positif), dan loop invarian (pernyataan logika yang selalu benar sebelum dan sesudah setiap kali loop berjalan), Anda dapat membuktikan bahwa loop sementara akan selesai (karena fungsi varian tidak dapat terus menurun) dan bahwa akhirnya klausa penjaga akan salah dan loop invarian menjadi benar.

Logika Floyd-Hoare tidak memiliki aturan untuk forloop atau apa pun yang membangun bahasa sebenarnya mungkin.

Namun, seperti yang dijelaskan oleh jawaban lain, untuk loop selalu dapat ditulis dalam bentuk while loop. Itu berarti bahwa mereka dapat beralasan tentang, hanya butuh sedikit lebih banyak pekerjaan.

Jika guru Anda memiliki kursus di universitas di mana ia harus memberikan bukti kebenaran programnya, ia mungkin menulis program hanya menggunakan loop. Saya tahu saya melakukannya. Dan begitu Anda terbiasa berpikir dalam hal fungsi penjaga dan varian dan invarian loop, mereka tampak sangat alami. Terlalu sering menggunakan loop adalah kebiasaan yang Anda lihat dengan lulusan CS, saya harus belajar untuk berhenti melakukan itu di bulan-bulan pertama saya sebagai pengembang profesional.

Di suatu tempat di ujung jalur, guru Anda salah mengartikan semua ini sebagai "programmer yang baik gunakan saat loop", sedangkan apa yang sebenarnya terjadi lebih seperti "beberapa lulusan CS mengubah kebiasaan pembuktian kebenaran mereka menjadi kebiasaan pemrograman praktis".


Ini tampaknya cukup konsisten dengan penilaian saya sendiri, meskipun berdasarkan pandangan yang berbeda. Logika Floyd-Hoare tidak memiliki alasan untuk mempertimbangkan forloop, yang tidak memiliki definisi tetap dan lebih kompleks, tanpa secara formal diperlukan.
babou

3

Sebenarnya, dalam beberapa hal, kebalikannya adalah benar.

Bahasa dengan hanya for-lingkaran bukan Turing-lengkap, ia hanya dapat menghitung fungsi primitif-rekursif, tidak semua fungsi yang dapat dihitung-Turing. Karena semua perhitungan dalam bahasa dengan for-lalu selalu berakhir, Masalah Henti dan semua Masalah Decidability lainnya berdasarkan itu, tidak muncul, jadi mungkin untuk secara mekanis memutuskan lebih banyak sifat statis dari program daripada dalam bahasa dengan while-lompat.

OTOH, bahasa dengan hanya bilangan asli, satu variabel, dan while-lingkaran adalah Turing-lengkap, sehingga tidak mungkin untuk memutuskan bahkan properti paling sederhana: akankah program ini mengembalikan hasil?


1
Sebuah forbahasa -hanya dapat menghasilkan whileperilaku -setara oleh decrementing variabel loop (dengan asumsi bahasa memungkinkan) selama iterasi yang tidak seharusnya mengakibatkan penghentian a. (Misalnya, for n in 1 to 2 { if condition then n := n-1 })
Blrfl

Ada banyak cara di mana a for loop dapat dibuat untuk loop selamanya, tergantung tentu saja pada definisi dalam bahasa yang ada. Dan satu loop tak terbatas sudah cukup untuk kelengkapan Turing.
babou

@Babou: Interpretasi yang paling umum dari loop for adalah loop yang mengulangi rentang atau koleksi yang terbatas. Tentu saja, dalam banyak bahasa Anda dapat meretas loop untuk berperilaku seperti loop sementara, tapi saya pikir bukan itu yang ada dalam pikiran Jorg.
Giorgio

0

Saya ingin mengatakan bahwa dalam kenyataan, tidak ada perbedaan. Pertanyaan Anda tidak relevan. Mungkin guru Anda mungkin bermaksud menggunakan while ketika tidak. iterasi tidak diketahui sebelumnya. Dalam banyak kasus kita perlu menggunakan loop sementara untuk mengekstrak digit dari no. saat pengguna memasukkan no. yang bisa berapa pun panjangnya. Secara teknis, kesamaan antara for & while loop adalah bahwa keduanya adalah entry-controlled loop di mana (test-expression / kondisi) dievaluasi sebelum masuk ke dalam loop body. Ini adalah perbedaan antara loop sementara & do-while.


-1

Kemungkinan berasal dari pemrograman C awal di mana, dengan norma saat ini, loop secara luas disalahgunakan dan disalahgunakan, terutama kondisi yang sedang dimodifikasi. Ketika pemrogram mulai memahami efek gaya pemrograman tertentu, penyalahgunaan dan penyalahgunaan persyaratan loop tidak disukai, dan pernyataan itu, sementara (bisa dibilang) sekali valid, tidak lagi memiliki kebenaran.

Pernyataan itu sama sekali tidak benar jika Anda hanya melihat definisi bahasa dan sintaksis dan mengabaikan bagaimana itu digunakan.

Namun, pernyataan itu sendiri menawarkan pelajaran berharga bagi siapa pun yang ingin memahaminya, sejarahnya, dan mengapa itu tidak lagi dianggap benar. - Apa ungkapan tentang belajar, kesalahan dan ulangi mereka .....


-10

Gurumu benar!

Alasannya berikut ini valid C

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

Anda tidak dapat menjamin variabel kondisi belum dirusak!


2
Bagaimana itu membuat whileloop lebih baik di sini?
milleniumbug

7
Oh ya? Sedangkan, dengan whileloop Anda benar-benar dapat menjamin bahwa variabel kondisi belum dirusak? Bahkan, mengutak-atik variabel kondisi adalah satu-satunya cara untuk keluar dari whileloop! Saya biasanya menahan diri dari downvoting hal, tetapi untuk jawaban ini, saya akan membuat pengecualian.
Mike Nakis

James, bisakah Anda menjelaskan mengapa ini bukan masalah sementara loop, Anda mungkin pada sesuatu tetapi orang-orang tampaknya tidak setuju untuk sejumlah bukti kontra dalam kasus loop sementara
Vincent

1
@VincentAdvocaat Saya akan mengatakan bahwa dengan loop sementara Anda mengharapkan variabel kondisi untuk dirusak dengan cara tertentu, sedangkan untuk loop Anda mengharapkannya akan diubah hanya pada bagian langkah dari for loop build itu sendiri. Ini prinsip paling keheranan lebih penting daripada banyak menyadari dalam pemrograman.
gbjbaanb

3
@ gbjbaanb benar, tetapi sejauh menyangkut pertanyaan, itu jauh dari prinsip yang paling tidak mengherankan menjadi provabilitas.
Mike Nakis
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.