ตัวหารร่วมมาก (G.C.D.) เขียนด้วยตัวเองทำยังไงดี
ตอนคิด ห.ร.ม. ในกระดาษก็ไม่ยากนะ แต่ในโปรแกรมคอมพิวเตอร์เขาเขียนกันยังไง?


โจทย์
ในคณิตศาสตร์ ตัวหารร่วมมาก หรือ ห.ร.ม. (greatest common divisor: gcd) ของจำนวนเต็มสองจำนวนซึ่งไม่เป็นศูนย์พร้อมกัน คือจำนวนเต็มที่มากที่สุดที่หารทั้งสองจำนวนลงตัว
โจทย์ จงเขียนโปรแกรมหา ห.ร.ม. ของจำนวนเต็ม 2 จำนวนที่กำหนดให้
ข้อมูลนำเข้า บรรทัดแรกระบุจำนวนเต็มสามจำนวน และ มีค่าไม่เกิน
ข้อมูลส่งออก มีบรรทัดเดียวเป็นห.ร.ม. ของทั้งสองจำนวน
ตัวอย่างข้อมูลนำเข้าและข้อมูลส่งออก
Input | Output |
---|---|
12 14 | 2 |
7 3 | 1 |
วิเคราะห์โจทย์
เชื่อว่าหลายคนที่เขียนโปรแกรมมานิดหน่อยก็คงรู้อยู่แล้วว่าการหา ห.ร.ม. เนี่ยมันมีฟังก์ชัน built-in มาให้ใน C++ หรือ ภาษาอื่นๆอยู่แล้ว (Python นี่ยิ่งง่ายเลย)
แต่ถ้าใช้อันนั้นมันก็ไม่ได้ทำให้เราเข้าใจวิธีการหา ห.ร.ม. อ่ะนะ ดังนั้นรอบนี้เลยจะเอาวิธีอื่นๆมาใช้กัน
แบบ 1: หาตัวประกอบทั้งหมด
ข้อสังเกตแรกคือถ้าสมมติเราดูค่าตัวนึงอยู่ สมมติให้เป็น เป็นค่าที่เราดูอยู่ จะได้ว่า
ถ้าเราสมมติให้ จะได้ว่า จะมีค่าไม่เกิน เพราะถ้าเกินไปแล้วจะผิดเงื่อนไขที่สมมติขึ้นมา ทำให้ได้ว่าเราก็แค่ลูปค่า ตั้งแต่ 1 ถึง
กลับมาที่โจทย์ดั้งเดิม เราจะได้ว่าการหาตัวประกอบร่วมของ และ สามารถทำได้ด้วยการลูปค่าถึง เพื่อหาค่าตัวประกอบของ แล้วเอาค่าตัวประกอบแต่ละตัวของ มาดูค่าว่ามีตัวไหนบ้างที่เป็นตัวประกอบของ บ้าง แล้วเอาค่ามากที่สุดมาเป็นคำตอบ
แบบ 2: ใช้ Euclidean Algorithm
สังเกตนิดนึงก่อนโดย สมมติว่าแทนให้ เป็น ห.ร.ม. ของ และ และ
สิง่ที่เราจะได้คือ
เรารู้ว่า หารทั้ง และ ลงตัวแปลว่า ก็ต้องหาร ลงตัวด้วย นั่นแปลว่า ห.ร.ม. ของ กับ ก็มีค่าเท่ากับ ห.ร.ม. ของ กับ ซึ่งถ้าใช้วิธีเดิมคิดต่อก็จะได้ว่า
ซึ่งแน่นอนว่า ก็ต้องหาร ลงตัวด้วย นั่นแปลว่า ก็ยังเป็น ห.ร.ม. ของ กับ ด้วย
และเราสามารถทำวิธีนี้ซ้ำไปเรื่อยๆได้ เลขที่เราต้องใช้คำนวณก็จะค่อยๆลดลงไปเรื่อยๆเหมือนกัน จนกระทั่งมีเลขนึงกลายเป็น ซึ่งมันจะได้สมการแบบนี้มา
ซึ่งแปลว่า ก็ต้องเป็น ห.ร.ม ของ และ ซึ่งก็คือ นั่นแหละ และก็แปลว่าขอแค่เราหา ได้ เราก็สามารถหา ห.ร.ม. ของ และ ได้นั่นเอง
เขียนเป็นโค้ดกัน
เราก็จะใช้หลักการเดียวกับที่อธิบายข้างต้นเลย ก็คือ
- เราต้องการให้ตัวหลังเป็น 0 เพื่อที่ตัวที่เหลือจะเป็นห.ร.ม. ของ a และ b
- ถ้าตัวหลังไม่ใช่ 0 แปลว่าเรายังไม่เจอห.ร.ม. เราก็จะค่อยๆหารไปตามสมการข้างต้น
1uint_8 _gcd(uint_8 a, uint_8 b) {2 if (b == 0) return a;3 return _gcd(b, a % b);4}