Tatal untuk bertukar halaman
Computer Science A · AP Computer Science A
if, while dan for
Aturcara menjalankan pernyataannya satu demi satu, mengikut tertib. Dua perkara mengubah tertib itu: pemilihan menentukan pernyataan yang dijalankan, dan lelaran menjalankan pernyataan sekali lagi.
Aturcara dalam rajah bermula dengan n = 5. Selagi n bukan 1, ia membahagi dua n jika genap, atau mendarabkannya tiga dan menambah 1 jika ganjil, dan mengira satu langkah. Berlian di atas ialah soalan gelung; berlian di bawahnya ialah soalan if. Token merah ialah titik pelaksanaan, dan kod di sebelahnya menyalakan baris yang sedang berjalan.
int n = 5; int steps = 0; while (n != 1) { if (n % 2 == 0) { n = n / 2; } else { n = 3 * n + 1; } steps++; } System.out.println(steps); n bergerak 5, 16, 8, 4, 2, 1. Syarat gelung disemak 6 kali: benar 5 kali, kemudian salah sekali, dan aturcara mencetak 5.
Bab ini ialah Unit 2 AP Computer Science A, 25–35% daripada skor aneka pilihan: ungkapan Boolean dan pernyataan if (2.1–2.6), gelung while dan for (2.7–2.8), algoritma piawai yang dibina daripadanya (2.9–2.10), gelung di dalam gelung (2.11), dan mengira kekerapan sesuatu pernyataan dijalankan (2.12).
tiga blok binaan
Setiap algoritma dibina daripada tiga perkara: penjujukan (langkah mengikut tertib), pemilihan (keputusan) dan pengulangan (gelung).
Pemilihan berlaku apabila cara algoritma diteruskan bergantung pada keputusan benar atau palsu. Pengulangan ialah proses yang berulang sehingga hasil yang dikehendaki dicapai. Kedua-duanya terdapat dalam arahan harian: “jika hujan, bawa payung” ialah pemilihan; “kacau sehingga gula larut” ialah pengulangan.
Algoritma boleh ditulis dengan kata-kata atau dilukis sebagai carta alir: kotak bagi setiap langkah, berlian bagi setiap keputusan benar-atau-palsu, dan anak panah yang kembali ke atas bagi pengulangan. Rajah kini menulis algoritma yang sama dengan kata-kata: “adakah n genap?”, “bahagi dua”, “kira satu langkah”. Kod itu menyatakan perkara yang sama dalam Java.
Tertib langkah mengubah hasilnya. Kedua-dua segmen ini mengandungi pernyataan yang sama:
int x = 3; x = x * 2; x = x + 1;
int x = 3; x = x + 1; x = x * 2;
Yang pertama meninggalkan x pada 7; yang kedua, pada 8. Dalam rajah, mengira satu langkah selepas gelung dan bukan di dalamnya akan mencetak 1, tidak kira berapa lama gelung berjalan.
operator hubungan
Ungkapan Boolean dinilai kepada satu daripada dua nilai, true atau false. Yang paling mudah membandingkan dua nilai dengan operator hubungan.
== dan != menguji sama ada dua nilai sama atau berbeza. <, >, <= dan >= membandingkan nombor. Dengan jenis primitif seperti int, double dan boolean, == membandingkan nilai sebenar. Dengan jenis rujukan, ia membandingkan rujukan: sama ada dua pemboleh ubah merujuk objek yang sama (2.6).
Dalam rajah, a menyimpan 7 dan b mengambil nilai 4, 7, 9. Setiap perbandingan menghasilkan satu blok, merah bagi benar:
| b = 4 | b = 7 | b = 9 | |
|---|---|---|---|
a == b | false | true | false |
a != b | true | false | true |
a < b | false | false | true |
a > b | true | false | false |
a <= b | false | true | true |
a >= b | true | true | false |
= menugaskan; == membandingkan. Hasil Boolean boleh disimpan seperti nilai lain: boolean same = a == b;
pemilihan sehala dan dua hala
Pernyataan pemilihan mengubah pelaksanaan berjujukan pernyataan. Pernyataan if menjalankan segmen kod yang berbeza bergantung pada nilai ungkapan Boolean.
Pemilihan sehala (if) mempunyai satu segmen, dijalankan hanya apabila syarat benar:
if (temp >= 30) { System.out.println("hot"); } System.out.println("done"); Dengan temp pada 34 ia mencetak hot then done; pada 22, hanya done. Baris terakhir berada selepas if, jadi ia sentiasa dijalankan.
Pemilihan dua hala (if-else) mempunyai dua segmen: badan if apabila syarat benar, badan else apabila syarat salah. Tepat satu daripadanya dijalankan.
if (temp >= 30) { System.out.println("hot"); } else { System.out.println("mild"); } System.out.println("done"); Rajah menghantar dua suhu menuruninya. Pada 34 token mengambil lorong benar dan mencetak hot; pada 22 lorong salah, mild. Kemudian kedua-duanya mencetak done.
if, else if, else
Pemilihan berbilang hala (if-else-if) menguji satu siri syarat mengikut tertib. Yang pertama benar menjalankan segmennya, dan tidak lebih daripada satu segmen dijalankan.
if (score >= 90) { grade = "A"; } else if (score >= 80) { grade = "B"; } else if (score >= 70) { grade = "C"; } else { grade = "F"; } Rajah menjatuhkan tiga skor menuruni rantai itu. 83 gagal score >= 90, lulus score >= 80, dan tersangkut: gred "B". Syarat di bawahnya tidak pernah disemak. 95 tersangkut pada get pertama, "A". 64 gagal ketiga-tiganya, jadi else di hujung dijalankan: "F". Tanpa else di hujung, nilai yang gagal setiap syarat tidak menjalankan sebarang segmen.
Oleh sebab syarat benar yang pertama menang, tertib penting. Uji score >= 70 dahulu dan 95 mendapat "C": setiap skor 70 atau lebih berhenti pada get pertama. Letakkan ujian yang paling ketat dahulu.
if di dalam if
Pernyataan if bersarang ialah pernyataan if, if-else atau if-else-if di dalam pernyataan if, if-else atau if-else-if yang lain.
if (age >= 16) { if (hasPermit) { System.out.println("may drive"); } else { System.out.println("needs a permit"); } } System.out.println("done"); Syarat dalam dinilai hanya jika syarat luar benar. Rajah menjalankan tiga orang. Umur 17 dengan permit lulus kedua-duanya dan mencetak may drive. Umur 17 tanpa permit lulus ujian luar dan gagal ujian dalam: needs a permit. Umur 14 gagal ujian luar, jadi token berpusing mengelilingi seluruh kotak: hasPermit tidak pernah dilihat, dan hanya done dicetak.
Pendakap menentukan if yang mana dimiliki oleh else. Di sini else berada di dalam pendakap luar, jadi ia berpasangan dengan if (hasPermit): sesiapa di bawah 16 langsung tidak mendapat mesej tentang permit.
!, && dan ||
Operator logik ! (bukan), && (dan) dan || (atau) menggabungkan ungkapan Boolean menjadi satu ungkapan yang sendirinya benar atau salah.
!a benar apabila a salah, dan salah jika sebaliknya. a && b benar hanya apabila kedua-duanya benar. a || b benar apabila a benar, b benar, atau kedua-duanya. Rajah menyelesaikan setiap gabungan, satu baris pada satu masa:
| a | b | a && b | a || b | !a |
|---|---|---|---|---|
| true | true | true | true | false |
| true | false | false | true | false |
| false | true | false | true | true |
| false | false | false | false | true |
Tertib keutamaan ialah ! dahulu, kemudian &&, kemudian ||. Jadi dengan a = false, b = true, c = false, ungkapan !a || b && c bermaksud (!a) || (b && c): true. Mengelompokkannya sebagai (!a || b) && c pula memberikan false. Tanda kurung menjelaskan tertibnya.
Operator hubungan didahulukan berbanding operator logik, jadi x > 0 && x < 10 membandingkan dahulu dan menggabungkan kemudian: ia benar bagi setiap x yang betul-betul antara 0 dan 10.
bahagian kanan mungkin tidak pernah dijalankan
Apabila operan kiri && atau || sudah menentukan hasilnya, Java tidak menilai operan kanan. Ini ialah penilaian litar pintas.
false && anything ialah salah, dan true || anything ialah benar, apa pun kata bahagian kanan. Jadi bahagian kanan dilangkau. Rajah menilai dua ungkapan, mula-mula dengan x = 4, kemudian dengan x = 0:
x != 0 && 10 / x > 2 x == 0 || 10 / x > 2
Dengan x = 4 kedua-dua belah bagi kedua-duanya dijalankan. 10 / 4 ialah 2 (pembahagian integer), tidak lebih daripada 2, jadi yang pertama ialah false dan begitu juga yang kedua.
Dengan x = 0, x != 0 ialah salah, jadi yang pertama ialah false serta-merta; dan x == 0 ialah benar, jadi yang kedua ialah true serta-merta. Dalam kedua-duanya 10 / x tidak dijalankan, dan ini memang baik: membahagi int dengan sifar melontarkan ArithmeticException.
Itu menjadikan operan kiri sebagai pengawal. Jika ditulis terbalik, 10 / x > 2 && x != 0 membahagi dahulu dan ranap apabila x ialah 0.
jadual kebenaran dan hukum De Morgan
Dua ungkapan Boolean adalah setara jika kedua-duanya bernilai sama dalam semua kes. Jadual kebenaran, dengan satu baris bagi setiap gabungan input, boleh membuktikannya.
Hukum De Morgan memberikan dua kesetaraan:
!(a && b) setara dengan !a || !b !(a || b) setara dengan !a && !b
Untuk menolak ! ke dalam tanda kurung, nafikan setiap bahagian dan tukar && dengan ||, atau || dengan &&. Dalam rajah, setiap lajur ungkapan kedua menggelongsor ke atas yang pertama: warnanya sepadan pada setiap baris.
| a | b | !(a && b) | !a || !b | !(a || b) | !a && !b |
|---|---|---|---|---|---|
| true | true | false | false | false | false |
| true | false | true | true | false | false |
| false | true | true | true | false | false |
| false | false | true | true | true | true |
Lupa menukar operator merosakkannya: !(a && b) dan !a && !b berbeza pada 2 daripada 4 baris. Perbandingan yang dinafikan membalikkan operatornya: !(x > 5) ialah x <= 5. Jadi !(x >= 1 && x <= 10) setara dengan x < 1 || x > 10.
== berbanding equals
Dua pemboleh ubah yang berbeza boleh menyimpan rujukan kepada objek yang sama. == dan != pada rujukan bertanya sama ada keduanya merujuk objek yang sama, bukan sama ada dua objek mempunyai kandungan yang sama.
String s1 = new String("atlas"); String s2 = s1; String s3 = new String("atlas"); String s4 = null; s2 = s1 menyalin rujukan, jadi s1 dan s2 menuding ke satu objek: s1 == s2 ialah true. s3 merujuk objek kedua dengan huruf yang sama: s1 == s3 ialah false.
Kelas sering mentakrifkan kaedah equals yang menyatakan bila dua objek dianggap sama, biasanya dengan membandingkan atributnya. Tali membandingkan aksara, jadi s1.equals(s3) ialah true. Bandingkan rentetan dengan equals, jangan sekali-kali ==.
Rujukan boleh dibandingkan dengan null menggunakan == atau !=, untuk mengetahui sama ada ia merujuk sebarang objek: s4 == null ialah true. (Mengatasi kaedah equals berada di luar skop kursus.)
semak, jalankan, semak lagi
Lelaran ialah satu bentuk pengulangan: pernyataan lelaran mengulang segmen kod sifar kali atau lebih, selagi ungkapan Booleannya benar.
Dalam gelung while, ungkapan Boolean dinilai sebelum setiap laluan melalui badan, termasuk yang pertama. Selagi ia benar badan dijalankan; apabila ia salah gelung berakhir dan aturcara diteruskan selepasnya.
int sum = 0; int k = 1; while (k <= 4) { sum += k; k++; } System.out.println(sum); Jadual jejak merekodkan pemboleh ubah setiap kali syarat disemak. Rajah mengisinya baris demi baris:
| k | sum | k <= 4 |
|---|---|---|
| 1 | 0 | true |
| 2 | 1 | true |
| 3 | 3 | true |
| 4 | 6 | true |
| 5 | 10 | false |
Syarat disemak 5 kali dan badan dijalankan 4 kali: semakan terakhir ialah yang salah. Gelung berakhir dengan k = 5, dan 10 dicetak.
tidak pernah, selama-lamanya, kurang satu
Kebanyakan pepijat gelung ialah salah satu daripada tiga: gelung tidak pernah dijalankan, tidak pernah berhenti, atau dijalankan satu kali terlalu banyak atau terlalu sedikit.
Jika ungkapan Boolean salah pada kali pertama, badan tidak pernah dilaksanakan. while (k < 5) dengan k pada 10 menyemak sekali dan meneruskan (baris atas).
Gelung tak terhingga berlaku apabila ungkapan Boolean sentiasa bernilai benar. Pada baris tengah k bergerak 1, 3, 5, 7, 9, … dan tidak pernah menjadi 6, jadi while (k != 6) tidak pernah menjadi salah. Gelung yang badannya tidak pernah mengubah pemboleh ubah dalam syaratnya melakukan perkara yang sama.
Ralat off-by-one ialah gelung yang berjalan satu kali terlalu banyak atau satu kali terlalu sedikit. Sepatutnya mencetak 1 hingga 5, gelung bawah mencetak 1234: while (k < 5) berhenti sebelum 5. k <= 5 membetulkannya.
int k = 1; while (k < 5) { System.out.print(k); k++; } Semak gelung pada tepinya: laluan pertama, laluan terakhir, dan semakan yang menamatkannya.
pemulaan, ungkapan Boolean, kemas kini
Gelung for meletakkan tiga bahagian gelung pengira dalam pengepalanya: pemulaan, ungkapan Boolean dan kemas kini.
for (int i = 0; i < 3; i++) { System.out.println(i); } Pemulaan dijalankan sekali, sebelum semakan pertama. Pemboleh ubah yang ditetapkannya ialah pemboleh ubah kawalan gelung. Ungkapan Boolean dinilai sejurus selepas pemulaan, dan kemudian lagi selepas setiap kemas kini, sehingga ia salah. Dalam setiap laluan, kemas kini dijalankan selepas seluruh badan dan sebelum semakan seterusnya.
Token rajah bergerak pemulaan → semakan → badan → kemas kini → semakan …. Kiraan di bawah setiap stesen: pemulaan 1, semakan 4, badan 3, kemas kini 3. Ia mencetak 0, 1, 2, masing-masing pada barisnya sendiri.
Gelung for boleh ditulis semula sebagai gelung while yang setara, dan sebaliknya:
int i = 0; while (i < 3) { System.out.println(i); i++; } Satu perbezaan: i yang diisytiharkan dalam pengepala for hanya wujud di dalam gelung; jika diisytiharkan sebelum gelung while, ia masih ada selepas itu.
% 10, / 10 dan % k
Dua algoritma piawai menggunakan operator baki: memecahkan integer digit demi digit, dan menguji sama ada satu integer boleh dibahagi tepat dengan yang lain.
Bagi int n positif, n % 10 ialah digit terakhirnya dan n / 10 (pembahagian integer) ialah n dengan digit itu dibuang. Ulang sehingga n ialah 0:
| n | n % 10 | n / 10 |
|---|---|---|
| 3725 | 5 | 372 |
| 372 | 2 | 37 |
| 37 | 7 | 3 |
| 3 | 3 | 0 |
int n = 3725; int sum = 0; int max = 0; int odd = 0; while (n > 0) { int d = n % 10; sum += d; if (d > max) { max = d; } if (d % 2 == 1) { odd++; } n /= 10; } Rajah mengupas digit 3725 dari kanan, 5, 2, 7, 3, dan setiap satunya melalui d.
a % b == 0 benar tepat apabila a boleh dibahagi tepat dengan b. 3725 % 5 ialah 0, jadi 3725 boleh dibahagi dengan 5; 3725 % 3 ialah 2, jadi ia tidak boleh dibahagi dengan 3. Ujian yang sama dengan 2 mengasingkan genap daripada ganjil, seperti yang dilakukan oleh d % 2 == 1 dalam gelung.
mengumpul semasa gelung berjalan
Tiga lagi algoritma piawai menyimpan nilai berjalan dalam pemboleh ubah yang diisytiharkan sebelum gelung dan dikemas kini di dalamnya: hasil tambah, minimum atau maksimum, dan kiraan.
Satu hasil tambah bermula pada 0 dan menambah setiap nilai: sum += d. Bagi 3725, sum berakhir pada 17.
Satu purata ialah hasil tambah dibahagi dengan bilangan nilai. Berhati-hati dengan pembahagian integer:
double avg = (double) sum / 4; int avgInt = sum / 4;
avg ialah 4.25; avgInt ialah 4, pecahan itu dibuang. Tukar jenis (cast) sebelum membahagi, bukan selepasnya.
Satu maksimum menyimpan nilai terbesar setakat ini dan menggantikannya setiap kali nilai yang lebih besar muncul: if (d > max). Di sini max berakhir pada 7. Mulakannya dengan nilai pertama, atau dengan nilai yang tiada nilai sebenar boleh lebih rendah daripadanya: 0 berfungsi hanya kerana digit tidak pernah negatif; secara amnya gunakan Integer.MIN_VALUE. Satu minimum ialah imej cermin, bermula pada Integer.MAX_VALUE dan menguji <; digit terkecil ialah 2.
Satu kiraan bilangan kali satu kriteria dipenuhi bermula pada 0 dan menambah 1 di dalam if: if (d % 2 == 1) mengira digit ganjil, iaitu 3 digit.
terbalikkan, dan kira subrentetan
Algoritma String menggerakkan indeks di sepanjang rentetan dan mengambil subrentetan pada setiap kedudukan: untuk membina rentetan baharu, atau untuk menguji atau mengira subrentetan yang mempunyai sesuatu sifat.
Untuk menterbalikkan rentetan, letakkan setiap aksara di hadapan apa yang telah dibina setakat ini. substring(i, i + 1) ialah aksara tunggal pada indeks i:
String word = "drawer"; String rev = ""; for (int i = 0; i < word.length(); i++) { rev = word.substring(i, i + 1) + rev; } rev bertambah panjang "d", "rd", "ard", "ward", "eward", "reward". (rev = rev + word.substring(i, i + 1) akan menyalin perkataan itu tanpa perubahan.)
Untuk mengira subrentetan yang memenuhi sesuatu kriteria, luncurkan tetingkap di sepanjang rentetan dan uji setiap satu:
String s = "banana"; int count = 0; for (int i = 0; i < s.length() - 1; i++) { if (s.substring(i, i + 2).equals("an")) { count++; } } Tetingkap substring(i, i + 2) melihat "ba", "an", "na", "an", "na": 2 sepadan, jadi count ialah 2. Tetingkap terakhir bermula pada indeks 4, jadi i mesti berhenti di bawah s.length() - 1; satu langkah lagi, substring(5, 7) melepasi hujung dan membuang StringIndexOutOfBoundsException.
Bandingkan subrentetan dengan equals. Untuk mengetahui sama ada mana-mana subrentetan mempunyai sifat itu, gelung yang sama boleh berhenti pada yang pertama ditemui, atau indexOf memulangkan tempat satu subrentetan tertentu mula-mula muncul, −1 jika tiada.
satu gelung di dalam satu gelung
Lelaran bersarang ialah gelung dalam badan gelung lain. Gelung dalam menjalankan semua lelarannya sebelum gelung luar bergerak ke lelaran seterusnya.
for (int r = 0; r < 3; r++) { for (int c = 0; c < 4; c++) { System.out.print(r * c + " "); } System.out.println(); } Bagi r = 0 gelung dalam menjalankan c dari 0 hingga 3; kemudian println menamatkan baris, dan hanya selepas itu r menjadi 1. Rajah menyalakan grid sel demi sel, baris demi baris: badan dalam dijalankan 3 × 4 = 12 kali dan mencetak
0 0 0 0 0 1 2 3 0 2 4 6
Had gelung dalam boleh bergantung pada pemboleh ubah luar. Di sini gelung dalam dijalankan r + 1 kali, jadi laluannya ialah 1, 2, 3, 4:
int count = 0; for (int r = 0; r < 4; r++) { for (int c = 0; c <= r; c++) { count++; } } count berakhir pada 10, sebuah segi tiga dan bukan segi empat tepat.
mengira kekerapan sesuatu pernyataan dijalankan
Kiraan pelaksanaan pernyataan ialah bilangan kali sesuatu pernyataan dijalankan. Ia biasanya ditentukan secara tidak formal, dengan menjejak beberapa laluan dan menaakul tentang gelung.
for (int i = 0; i < n; i++) { count++; } Dengan i dari 0 hingga n − 1, count++ dijalankan n kali. Semakan i < n dijalankan n + 1 kali: sekali lagi, untuk menamatkan gelung.
for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { count++; } } Secara bersarang, setiap satu daripada n laluan luar menjalankan gelung dalam n kali: count++ dijalankan n × n kali. Bagi n = 6 itu ialah 6 berbanding 36; bagi n = 8, 8 berbanding 64. Rajah bertambah kedua-duanya apabila n meningkat: menggandakan n menggandakan yang satu dan mengempatkan yang lain.
Kira daripada had gelung. for (int i = 1; i <= n; i++) juga dijalankan n kali; i < n bermula pada 1 dijalankan n − 1; segi tiga seperti yang pada halaman terakhir dijalankan 1 + 2 + … + n kali. Membandingkan kiraan sebegini ialah cara untuk mengatakan satu gelung lebih pantas daripada yang lain tanpa jam randik.