Transcript while (2)
418115: การโปรแกรมโครงสร้าง คาสัง่ while (2) ประมุข ขันเงิน [email protected] โปรแกรมเช็คจานวนเฉพาะ ให้ ผ้ ูใช้ ป้อนจำนวนเต็มบวกมำหนึ่งตัว แล้ วบอกว่ำมันเป็ นจำนวนเฉพำะหรือไม่ Enter n: 2 2 is a prime number. Enter n: 7 7 is a prime number. Enter n: 6 6 is not a prime number. จานวนเฉพาะ จำนวนเฉพำะคืออะไร? จำนวนเต็มบวก (ฉะนั้นไม่นับ 0 หรือจำนวนเต็มลบ) ไม่ใช่จำนวนเต็มลบ แยกตัวประกอบไม่ได้ กล่ำวคือ จำนวนเต็มบวกที่หำรมันลงตัวมีเพียงแค่สองตัว คือ 1 กับตัวมันเอง เช็คว่ำจำนวนเป็ นจำนวนเฉพำะได้ อย่ำงไร? สมมติว่ำจำนวนที่เรำต้ องกำรเช็คคือ n จำนวนที่หำรมันได้ มีแค่สองตัวคือ 1 กับ n ดังนั้น 2, 3, 4, …, n-1 ต้ องหำรมันไม่ลงตัว ฉะนั้นเรำเช็ค 2, 3, 4, …, n-1 ทีละตัวว่ำหำร n ลงตัวหรือไม่? มีสกั ตัวที่หำรลงตัว ไม่ใช่จำนวนเฉพำะ ไม่มีสกั ตัวที่หำรลงตัว เป็ นจำนวนเฉพำะ ออกแบบโปรแกรม รับ n ตั้งลูปโดยใช้ k เป็ นตัวแปร counter k มีค่ำ 2 ถึง n-1 สำหรับ k แต่ละค่ำเช็คว่ำ n % k == 0 หรือไม่? ถ้ ำใช่ ให้ จำไว้ ว่ำมีเลขหำรลงตัว หลังจำกลูปเสร็จกำรทำงำน ให้ ไปเช็คว่ำมีเลขหำรลงตัวหรือไม่ ถ้ ำใช่ แสดงว่ำไม่เป็ นจำนวนเฉพำะ ถ้ ำไม่ใช่ แสดงว่ำเป็ นจำนวนเฉพำะ ลูป int is_prime = 1; int k = 2; while (k < n) { if (n % k == 0) is_prime = 0; k++; } ทัง้ โปรแกรม #include <stdio.h> int main() { int n; printf("Enter n: "); scanf("&d", &n); int is_prime = 1; int k = 2; while (k < n) { if (n % k == 0) is_prime = 0; k++; } if (is_prime && n != 1) printf("%d is a prime number.\n", n); else printf("%d is not a prime number.\n", n); return 0; } คาสัง่ break เคยเจอมำแล้ วในคำสั่ง switch สำมำรถใส่ไว้ ตรงในก็ได้ ในส่วนที่เป็ นคำสั่งที่ต้องกำรวนซำ้ ใน คำสั่ง while เมื่อเจอคำสั่ง break แล้ วลูป while จะเลิกกำรทำงำนทันที มักใช้ ควบคู่กบ ั คำสั่ง if เสมอ โปรแกรมเช็คจานวนเฉพาะ เรำไม่จำเป็ นต้ องให้ k มีค่ำตั้งแต่ 2 ถึง n-1 เสมอ ถ้ ำมีเลขสักตัวหำรลงตัว แสดงว่ำไม่ใช่จำนวนเฉพำะแล้ ว ดังนั้นไม่มคี วำมจำเป็ นต้ องเช็คจำนวนอื่นอีก เรำต้ องกำรหยุดกำรทำงำนของลูปทันทีท่ี n%k == 0 สำมำรถใช้ คำสั่ง break ได้ ในกรณีน้ ี ลูปใหม่ทเี่ ร็วขึน้ int is_prime = 1; int k = 2; while (k < n) { if (n % k == 0) { is_prime = 0; break; } k++; } โปรแกรมสาหรับแยกตัวประกอบ รับจำนวนเต็มหนึ่งตัวจำกผู้ใช้ แยกตัวประกอบของจำนวนเต็มที่ผ้ ูใช้ ให้ มำ Enter a positive integer: 128 128 = 2 * 2 * 2 * 2 * 2 * 2 * 2 Enter a positive integer: 365 365 = 5 * 73 Enter a positive integer: 97 97 = 97 การแยกตัวประกอบ แยกตัวประกอบคืออะไร? กำรเขียนจำนวนเต็มอยู่ในรูปผลคูณของจำนวนเฉพำะ ทำอย่ำงไรดีถงึ จะแยกได้ สมมติว่ำเลขที่เรำต้ องกำรจะแยกตัวประกอบคือ n สมมติให้ n > 1 (กรณี n = 1 ไม่มีอะไร) หำจำนวนเฉพำะมำสักตัวที่หำร n ลงตัว สมมติว่ำจำนวนเฉพำะนี้คือ p ถ้ ำจำนวนเฉพำะนั้นหำร n ลงตัว เรำก็พิมพ์มัน แล้ วลบมันออกจำกตัวประกอบของ n ด้ วยกำรสั่ง n = n/p การแยกตัวประกอบ 48 6 หำร 2 ลงตัว หำร 2 ลงตัว 48 24 63 24 3 หำร 2 ลงตัว หำร 3 ลงตัว 24 12 31 12 หำร 2 ลงตัว 12 6 จบกำรทำงำน หาจานวนเฉพาะทีห่ าร n ลงตัว สมมติว่ำ n > 1 ลองเปลี่ยนคำถำมเป็ นว่ำ “จำนวนเฉพำะที่น้อยที่สดุ ที่หำร n ลงตัวคืออะไร?” สังเกต คำถำมนี้มค ี ำตอบเดียวกับคำถำมที่ว่ำ “จำนวนที่น้อยที่สดุ ที่มำกกว่ำ 1 ที่หำร n ลงตัวคืออะไร?” หาจานวนเฉพาะทีห่ าร n ลงตัว ทำไม? สมมติว่ำ m เป็ นจำนวนที่น้อยที่สดุ ที่มำกกว่ำ 1 ที่หำร n ลงตัว สมมติอกี ว่ำ m ไม่ใช่จำนวนเฉพำะ แสดงว่ำ m ตัวแยกตัวประกอบได้ สมมติให้ p เป็ นจำนวนเฉพำะที่หำร m ลงตัว เรำรู้ว่ำ p < m และ p > 1 แต่ p ก็หำร n ลงตัว ฉะนั้น m ไม่ใช่จำนวนที่น้อยที่สดุ ที่มำกกว่ำ 1 ที่หำร n ลงตัว เกิดข้ อขัดแย้ ง หาจานวนเฉพาะทีห่ าร n ลงตัว หำจำนวนเฉพำะที่น้อยที่สดุ ที่หำร n ลงตัว คือกำรหำจำนวนที่มำกกว่ำ 1 ที่น้อยที่สดุ ที่หำร n ลงตัว หำอย่ำงไร? เริ่มจำก p = 2 เช็คว่ำ n%p == 0 หรือไม่? ถ้ ำใช่กจ็ บ ถ้ ำไม่ใช่กเ็ พิ่มค่ำ p ขึ้นหนึ่ง หาจานวนเฉพาะทีห่ าร n ลงตัว int p = 2; while (n % p != 0) p++; ลูป หำ p หนึ่งตัวที่หำร n ลงตัว พิมพ์ p ลบ p ออกจำกควำมเป็ นตัวประกอบของ n n = n/p หยุดเมื่อไหร่ ? n == 1 ลูป printf("%d = ", n); while (n > 1) { int p = 2; while (n % p != 0) p++; if (n/p==1) printf("%d\n", p); else printf("%d * ", p); n = n/p; } ทัง้ โปรแกรม #include <stdio.h> int main() { int n; printf("Enter a positive integer: "); scanf("&d", &n); if (n == 1) printf("1 = 1\n"); else { printf("%d = ", n); while (n > 1) { int p = 2; while (n % p != 0) p++; if (n/p==1) printf("%d\n", p); else printf("%d * ", p); n = n/p; } } return 0; } เลขพาลินโดรม เลขพำลินโดรมคือเลขที่เขียนจำกหลังไปหน้ ำแล้ วมีค่ำเท่ำเดิม เช่น 12321 เป็ นเลขพำลินโดรม แต่ 123 ไม่ใช่ เพรำะ 123 ไม่เท่ำกับ 321 สังเกตว่ำเลขพำลินโดรมจะต่อท้ ำยด้ วย 0 ไม่ได้ โปรแกรมตรวจสอบเลขพาลินโดรม อ่ำนจำนวนเต็มบวกจำกผู้ใช้ หนึ่งตัว ชนิด int ไม่เกิน 6 หลัก แล้ วบอกว่ำเลขนั้นเป็ นพำลินโดรมหรือไม่ Enter n: 12321 12321 is a palindrome Enter n: 4567 4567 is not a palindrome ออกแบบโปรแกรม พำลินโดรมคืออะไร? เขียนกลับหลังแล้ วได้ ตัวเติม จะทดสอบพำลินโดรมอย่ำงไร? ก็ลองเขียนกลับหลังดูแล้ วเทียบว่ำเท่ำกับตัวเดิมหรือไม่ เขียนกลับหลัง สมมติว่ำมีเลข n =123456 สำมำรถเขียนกลับหลังโดยกำรมีเลขอีก 1 ตัว ตอนแรกเป็ น 0 กระบวนกำร n = 123456 n = 12345 n = 1234 n = 123 n = 12 n=1 n=0 m=0 m=6 m = 65 m = 654 m = 6543 m = 65432 m = 654321 เขียนกลับหลัง ในแต่ละขั้น ดึงตัวหลังของ n ออกมำ เอำตัวหลังของ n ไปต่อท้ ำย m ลบตัวหลังออกจำก n กล่ำวคือ int d = n % 10; n = n / 10; m = m*10 + d; หยุดเมื่อใด? เมื่อ n = 0 เขียนกลับหลัง int m = 0; while (n > 0) { int d = n % 10; n = n / 10; m = m*10 + d; } ทัง้ โปรแกรม #include <stdio.h> int main() { int n; printf("Enter n: "); scanf("%d", &n); int nn = n; int m = 0; while (n > 0) { int d = n % 10; n = n / 10; m = m*10 + d; } if (m == nn) printf("%d is a palindrome\n", nn); else printf("%d is not a palindrome\n", nn); return 0; } คาถาม ในจำนวนเต็มตั้งแต่ 1 ถึง 1,000,000 มีจำนวนเต็มกี่ตวั ที่เป็ นทั้ง จำนวนเฉพำะ และ พำลินโดรม? จำนวนเต็มเหล่ำนั้นคืออะไรบ้ ำง? ออกแบบโปรแกรม เรำรู้วิธเี ช็คพำลินโดรม เรำรู้วธิ เี ช็คจำนวนเฉพำะ ฉะนั้นเอำจำนวนเต็มมำทีละตัวแล้ วเช็คว่ำมันเป็ นทั้งสองอย่ำงหรือไม่ แล้ วก็นับจำนวนที่ใช่ ลูป int n = 2; while (n <= 999999) { [ตรวจว่า n เป็ นพาลินโดรมหรือไม่] [ตรวจว่า n เป็ นจานวนเฉพาะหรือไม่] [ถ้าใช่ท้ งั คู่พิมพ์ n] } ลูป (ฉบับเต็ม) int n = 2; while (n <= 999999) { int m = 0; int nn = n; while (nn > 0) { int d = nn % 10; nn = nn / 10; m = m*10 + d; } int is_palindrome = (m == n); int is_prime = 1; int k = 2; while (k < n) { if (n % k == 0) { is_prime = 0; break; } k++; } if (is_palindrome && is_prime) printf("%d\n", n); n++; } ปัญหา มันช้ ำ ทำไม? กำรเช็คจำนวนเฉพำะ ถ้ ำจะเช็คว่ำ 983,139 เป็ นจำนวนเฉพำะหรือไม่จะต้ องวนรอบทั้งหมดกี่รอบ? อำจจะถึง 983,137 รอบ! ฉะนั้นกรณีเลวสุดโปรแกรมจะต้ องวนรอบประมำณ 1,000,000 * 1,000,000 (แต่ควำมจริงน้ อยกว่ำนี้มำก) ทาให้มนั เร็วขึน้ ? กำรเช็คจำนวนเฉพำะช้ ำ ต้ องพยำยำมหลีกเลี่ยง เรำสนใจเฉพำะเลขที่เป็ นทั้งพำลินโดรมและจำนวนเฉพำะ ดังนั้นถ้ ำเลขใดไม่เป็ นพำลินโดรมแล้ วเรำก็ไม่ต้องไปเช็คว่ำมันเป็ นจำนวนเฉพำะก็ ได้ คาสัง่ continue เมื่อสั่งแล้ วจะไปเริ่มต้ นลูปใหม่อกี ครั้งหนึ่ง ข้ ำมคำสั่งส่วนที่เหลือของลูปไป มักใช้ ควบคู่กบ ั คำสั่ง if หลีกเลีย่ งการเช็คจานวนเฉพาะ int is_prime = 1; int k = 2; while (k < n) { if (n % k == 0) { is_prime = 0; break; } k++; } int n = 2; while (n <= 999999) { int m = 0; int nn = n; while (nn > 0) { int d = nn % 10; nn = nn / 10; m = m*10 + d; } int is_palindrome = (m == n); if (!is_palindrome) { n++; continue; } if (is_palindrome && is_prime) printf("%d\n", n); n++; }