Leon's curiosities

The More I Learn, The More I Want To Learn.

มาหาค่าพายจากการสุ่มเลขกันเถอะ

Saturday, May 27, 2023, 07:13 PM

ให้ฟังก์ชันนึงสมมติว่าชื่อ rand() สามารถสุ่มเลขระหว่าง 0 ถึง 1 ได้ จงหาค่าพายจากฟังก์ชันนี้ โดยสามารถเรียกฟังก์ชัน rand() ได้ไม่จำกัดครั้ง

กล่าวคือให้หาค่าพายจากการสุ่มเลขระหว่าง 0 ถึง 1

โจทย์นี้1 ได้มาจาก YouTube ช่อง Joma Tech ดูเป็นโจทย์ที่ไร้สาระมากเลยใช่มั้ย แบบจะไปทำได้ไง แต่ถ้าเห็นเฉลยแล้วเชื่อว่าทุกคนจะอ๋อแน่นอน เฉลยของโจทย์นี้บอกได้ว่าสวยมาก อยากให้ทุกคนลองคิดดูก่อน แล้วค่อยไปดูเฉลยด้านล่างนะ😋

เฉลยจ้า

หลักการคือเราต้องมองโจทย์ให้เป็นระนาบ 2 มิติ โดยที่แต่ละแกนจะยาวตั้งแต่ 0 ถึง 1 แบบนี้

2D plane

เราจะทำการสุ่มจุดบนระนาบนี้ด้วยวิธีการสุ่มค่า x และ y ทีละค่า แล้วเราจะได้จุดจุดหนึ่งขึ้นมา เช่นถ้าเราสุ่มค่า x ได้ 0.6 และ y ได้ 0.4 ก็จะเป็นจุด $(0.6, 0.4)$ ขึ้นมา

2D plane with 1 point

ทีนี้สมมติว่าเราสุ่มลงไปให้ได้ซักประมาณ 20 จุด และตีกรอบสี่เหลี่ยมขนาด 1x1 ครอบไว้ด้วย

2D plane with 20 points and 1x1 rectangle

และแน่นอนว่าถ้าเราพูดถึงค่า $\pi$ ก็ต้องมีวงกลมเข้ามาเกี่ยวข้อง ดังนั้นเราจะเอาวงกลมขนาดรัศมี 1 มาวาดด้วย

2D plane with 20 points and 1x1 rectangle and circle

จะเห็นได้ว่าในสี่เหลี่ยม 1x1 นี้ มีทั้งจุดที่อยู่ในเสี้ยววงกลม และจุดที่อยู่นอกวงกลม ลองจินตนาการว่าถ้าเราสุ่มจุดเพิ่มลงไปบนระนาบเรื่อย ๆ จนมากพอ จะสังเกตได้ว่า

\[\frac{N_c}{N_s} \approx \frac{A_c}{A_s}\]

โดยให้

  • $N_c$ คือ จำนวนจุดที่อยู่ในเสี้ยววงกลม
  • $N_s$ คือ จำนวนจุดทั้งหมดในสี่เหลี่ยม
  • $A_c$ คือ พื้นที่ของเสี้ยววงกลม
  • $A_s$ คือ พื้นที่ของสี่เหลี่ยม

ดังรูป

2D plane with filled 1x1 rectangle and filled circle

ซึ่งพื้นที่สี่เหลี่ยมในที่นี้คือ $1 \times 1 = 1$ ตร.หน่วย และพื้นที่เสี้ยววงกลมคือ $\frac{\pi(1)^2}{4} = \frac{\pi}{4} $ ตร.หน่วย ดังนั้นจะได้ว่า

\[\begin{align} \frac{N_c}{N_s} &\approx \frac{A_c}{A_s} \\ \frac{N_c}{N_s} &\approx \frac{\frac{\pi}{4}}{1} \\ \pi &\approx 4 \times \frac{N_c}{N_s} \end{align}\]

ฉะนั้นถ้าเราสามารถหาจำนวนจุดที่อยู่ภายในเสี้ยววงกลม และจำนวนจุดที่อยู่ในสี่เหลี่ยมได้ เราก็จะสามารถหาค่า $\pi$ ได้

แล้วเราจะรู้ได้ยังไงล่ะว่าจุดนั้นอยู่ในพื้นที่วงกลมรึเปล่า ง่ายมาก! แค่หาระยะทางหว่างจุดใด ๆ ถึงจุดศูนย์กลาง $(0, 0)$ ถ้าระยะห่างนั้นน้อยกว่าหรือเท่ากับรัศมี (1 หน่วย) ก็แปลว่าจุดนั้นอยู่ในวงกลม ซึ่งสมการระยะห่างจุดสองจุด $(x_1, y_1)$ และ $(x_2, y_2)$ คือ

\[d = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}\]

และเราสามารถแทนค่า $x_2, y_2$ ด้วย $(0, 0)$ ได้เลย ดังนั้นสมการระยะห่างจะกลายเป็น

\[d = \sqrt{x^2 + y^2}\]

ดังนั้นเราก็สามารถเขียนโปรแกรมเพื่อหาค่า $\pi$ ได้ดังนี้

import random

def rand():
    return random.uniform(0, 1)

def is_in_circle(x, y):
    return x**2 + y**2 <= 1 # ใช้ 1 ได้เลยเพราะรากที่สองของ 1 ก็คือ 1

# n คือจำนวนจุดทั้งหมดที่เราจะสุ่มลงไป
def estimate_pi(n):
    num_in_circle = 0
    for _ in range(n):
        x = rand()
        y = rand()
        if is_in_circle(x, y):
            num_in_circle += 1
    return 4 * num_in_circle / n

Shalluv

author