1 🎯 A formula answers. A program argues back. · สูตรให้คำตอบ โปรแกรมเถียงกลับได้ · 公式给你答案,程序会跟你争
🇬🇧 English
A physics formula hands you one number and asks you to trust it. A program lets you ask the next question: what if the ball were heavier, what if there were no air, what if I threw it at 39 degrees instead of 45?
Four short programs here. None needs a library, none needs the internet, and none is longer than a page. What they have in common is that each one puts a rule you were told to memorise on trial, and two of them find it guilty.
You need Python and nothing else. The pictures were drawn with matplotlib, but the physics runs without it.
🇹🇭 ไทย
สูตรฟิสิกส์ยื่นตัวเลขมาให้หนึ่งตัวแล้วขอให้คุณเชื่อ ส่วนโปรแกรมให้คุณถามคำถามถัดไปได้ ถ้าลูกบอลหนักกว่านี้ล่ะ ถ้าไม่มีอากาศล่ะ ถ้าขว้างที่ 39 องศาแทน 45 องศาล่ะ
ที่นี่มีโปรแกรมสั้น ๆ สี่ตัว ไม่ต้องใช้ไลบรารี ไม่ต้องต่ออินเทอร์เน็ต และไม่มีตัวไหนยาวเกินหนึ่งหน้า สิ่งที่เหมือนกันคือแต่ละตัวเอากฎที่คุณถูกสั่งให้ท่องจำมาขึ้นศาล และสองตัวในนั้นตัดสินว่าผิดจริง
คุณต้องมีแค่ Python รูปกราฟวาดด้วย matplotlib แต่ตัวฟิสิกส์รันได้โดยไม่ต้องมีมัน
🇨🇳 中文
物理公式递给你一个数字,然后要你相信它。程序则让你问下一个问题:如果球更重呢?如果没有空气呢?如果我用 39 度而不是 45 度扔呢?
这里有四个短程序。都不需要库,不需要联网,也没有一个超过一页。它们的共同点是:每一个都把一条你被要求背下来的规则送上法庭,其中两条被判有罪。
你只需要 Python。图是用 matplotlib 画的,但物理部分没有它也能跑。
2 🪨 Drop a stone, two ways · ปล่อยก้อนหิน สองวิธี · 扔一块石头,用两种方法
🇬🇧 English
The formula says a dropped stone has fallen ½gt² metres. The simulation does not know that formula. It knows only two things, repeated in small steps: gravity changes the speed, and the speed changes the position.
Run it and they agree — nearly. The gap is the interesting part, and it is not random. Take a step ten times smaller and the error gets ten times smaller.
🇹🇭 ไทย
สูตรบอกว่าก้อนหินที่ถูกปล่อยตกไปแล้ว ½gt² เมตร โปรแกรมจำลองไม่รู้จักสูตรนั้น มันรู้แค่สองอย่างแล้วทำซ้ำเป็นก้าวเล็ก ๆ คือแรงโน้มถ่วงเปลี่ยนความเร็ว และความเร็วเปลี่ยนตำแหน่ง
พอรันจริงทั้งสองก็ตรงกัน เกือบตรง ช่องว่างที่เหลือคือส่วนที่น่าสนใจ และมันไม่ได้สุ่ม ถ้าย่อก้าวให้เล็กลงสิบเท่า ความคลาดเคลื่อนก็เล็กลงสิบเท่า
🇨🇳 中文
公式说,落下的石头已经掉了 ½gt² 米。模拟不知道这个公式。它只知道两件事,并且以很小的步长不断重复:重力改变速度,速度改变位置。
跑一下,两者吻合 —— 几乎吻合。那点差距才是有意思的地方,而且它不是随机的。把步长缩小十倍,误差也缩小十倍。
terminal
python falling.py
falling.py
"""falling.py - drop a stone, two ways: with the formula, and step by step.
python falling.py
The formula says where the stone is at any time. The simulation does not know the
formula: it only knows that gravity changes the speed, and speed changes the position,
and it repeats that in small steps.
They should agree. Where they disagree tells you something useful about simulations.
"""
G = 9.81 # metres per second, per second - how fast "how fast" changes
HEIGHT = 45.0 # a stone dropped from a tenth-floor balcony
def exact(t):
"""Where the stone is after t seconds, from the formula in the textbook."""
return HEIGHT - 0.5 * G * t * t
def simulate(dt, stop):
"""Step through time in jumps of dt seconds. No formula, just repetition."""
y, v, t = HEIGHT, 0.0, 0.0
while t < stop - 1e-12:
y = y - v * dt # v is how fast it is falling, so y goes down
v = v + G * dt # then gravity makes it a little faster
t = t + dt
return y
if __name__ == "__main__":
t = 2.0
print(f"a stone dropped from {HEIGHT} m, where is it after {t} s?")
print(f" the formula says {exact(t):8.4f} m above the ground")
print()
print(" step size simulation difference")
for dt in (0.5, 0.1, 0.01, 0.001):
y = simulate(dt, t)
print(f" {dt:>7} s {y:8.4f} m {y - exact(t):+8.4f} m")
print()
print("halve the step, halve the error. The simulation is not wrong,")
print("it is approximate, and you can see exactly how approximate.")
what it printed
a stone dropped from 45.0 m, where is it after 2.0 s?
the formula says 25.3800 m above the ground
step size simulation difference
0.5 s 30.2850 m +4.9050 m
0.1 s 26.3610 m +0.9810 m
0.01 s 25.4781 m +0.0981 m
0.001 s 25.3898 m +0.0098 m
halve the step, halve the error. The simulation is not wrong,
it is approximate, and you can see exactly how approximate.
½·g·t·dt exactly — 4.9 m at half-second steps, 1 cm at millisecond steps. A simulation is not a worse formula. It is a formula you can watch being built, with an error you can shrink on purpose.
สองวิธีในการรู้เรื่องเดียวกัน พร้อมระยะห่างที่วัดได้ระหว่างทั้งสอง ความคลาดเคลื่อนเท่ากับ ½·g·t·dt พอดี คือ 4.9 เมตรเมื่อก้าวครึ่งวินาที และ 1 เซนติเมตรเมื่อก้าวระดับมิลลิวินาที การจำลองไม่ใช่สูตรที่ด้อยกว่า แต่เป็นสูตรที่คุณเฝ้าดูมันถูกสร้างขึ้นได้ และมีความคลาดเคลื่อนที่คุณตั้งใจย่อให้เล็กลงได้
认识同一件事的两种方式,以及它们之间一段量得出来的距离。误差正好是 ½·g·t·dt —— 半秒步长时是 4.9 米,毫秒步长时是 1 厘米。模拟不是更差的公式,而是一个你能看着它被搭起来的公式,并且误差可以按你的意思缩小。
y + v*dt instead of y - v*dt — and it reported the stone rising to 64 m from a 45 m balcony. The simulation was perfectly consistent with itself and completely wrong. What caught it was a separate check against ½gt², an answer known on paper. Always check a simulation against something you did not compute with it.
โปรแกรมนี้เวอร์ชันแรกทำให้ก้อนหินตกขึ้นข้างบน เครื่องหมายผิดตัวเดียว คือ y + v*dt แทนที่จะเป็น y - v*dt มันจึงรายงานว่าก้อนหินลอยขึ้นไปถึง 64 เมตรจากระเบียงที่สูง 45 เมตร การจำลองสอดคล้องกับตัวเองอย่างสมบูรณ์และผิดอย่างสิ้นเชิง สิ่งที่จับได้คือการตรวจแยกต่างหากเทียบกับ ½gt² ซึ่งเป็นคำตอบที่รู้อยู่แล้วบนกระดาษ ให้ตรวจการจำลองกับสิ่งที่คุณไม่ได้คำนวณด้วยตัวมันเองเสมอ
这个程序的第一版让石头往上掉。一个符号写错 —— y + v*dt 写成了该写的 y - v*dt —— 它就报告说石头从 45 米的阳台升到了 64 米。那个模拟跟它自己完全自洽,同时完全错误。抓住它的,是另一项对照 ½gt² 的独立检查,一个纸上就能算出的答案。永远要拿模拟去对照一个不是它自己算出来的东西。
3 🎾 Now let the air push back · ทีนี้ให้อากาศดันกลับบ้าง · 现在让空气推回来
🇬🇧 English
Air resistance grows with speed, so the faster the ball falls the harder the air pushes. Eventually the push equals the weight, the ball stops speeding up, and it falls the rest of the way at a steady speed. That speed has a name: terminal velocity.
There is a tidy formula for that final speed, √(mg/K), and the program agrees with it to four decimal places. There is no tidy formula for the rest of the fall. That is the honest reason to simulate: not because it is modern, but because the algebra has run out.
🇹🇭 ไทย
แรงต้านอากาศเพิ่มขึ้นตามความเร็ว ยิ่งลูกบอลตกเร็วเท่าไร อากาศก็ยิ่งดันแรงขึ้นเท่านั้น สุดท้ายแรงดันจะเท่ากับน้ำหนัก ลูกบอลก็หยุดเร่ง แล้วตกส่วนที่เหลือด้วยความเร็วคงที่ ความเร็วนั้นมีชื่อว่าความเร็วปลาย
ความเร็วสุดท้ายนั้นมีสูตรสวย ๆ คือ √(mg/K) และโปรแกรมก็ตรงกับมันถึงทศนิยมสี่ตำแหน่ง แต่ช่วงที่เหลือของการตกไม่มีสูตรสวย ๆ นี่คือเหตุผลที่ซื่อสัตย์ในการจำลอง ไม่ใช่เพราะมันทันสมัย แต่เพราะพีชคณิตไปต่อไม่ไหวแล้ว
🇨🇳 中文
空气阻力随速度增大,球掉得越快,空气推得越狠。最终推力等于重力,球不再加速,剩下的路程以恒定速度下落。这个速度有个名字:终端速度。
这个最终速度有一个漂亮的公式 √(mg/K),程序和它吻合到小数点后四位。但下落过程的其余部分没有漂亮的公式。这才是模拟的诚实理由:不是因为它时髦,而是因为代数走不下去了。
air.py
"""air.py - the same drop, but now the air pushes back.
python air.py
Air resistance grows with speed. The faster the ball falls, the harder the air pushes,
until the push equals the weight and the ball stops speeding up. That speed has a name:
terminal velocity.
There is a formula for the final speed. There is no simple formula for the whole fall,
which is exactly why you simulate it.
"""
import math
G = 9.81
MASS = 0.057 # a tennis ball, in kilograms
RADIUS = 0.033 # metres
RHO = 1.2 # density of air, kg per cubic metre
DRAG = 0.5 # drag coefficient of a sphere, roughly
K = 0.5 * RHO * DRAG * math.pi * RADIUS ** 2 # the air-resistance constant
DT = 0.001
def terminal_speed():
"""The speed where the air pushes up exactly as hard as gravity pulls down."""
return math.sqrt(MASS * G / K)
def fall(height, with_air=True):
"""Drop the ball and report (time to land, speed when it lands)."""
y, v, t = height, 0.0, 0.0
while y > 0:
push = K * v * v if with_air else 0.0 # air pushes back, harder when fast
a = G - push / MASS
v = v + a * DT
y = y - v * DT
t = t + DT
return t, v
if __name__ == "__main__":
print(f"tennis ball: {MASS} kg, air constant K = {K:.6f}")
print(f"terminal speed from the formula: {terminal_speed():.2f} m/s")
print()
print(" height no air: time, speed with air: time, speed")
for h in (10, 45, 100, 500):
t0, v0 = fall(h, with_air=False)
t1, v1 = fall(h, with_air=True)
print(f" {h:>4} m {t0:5.2f} s {v0:6.2f} m/s {t1:5.2f} s {v1:6.2f} m/s")
print()
print("from 10 m the air hardly matters. From 500 m it decides everything:")
print(f"the ball never goes faster than about {terminal_speed():.0f} m/s, however far it falls.")
what it printed
tennis ball: 0.057 kg, air constant K = 0.001026
terminal speed from the formula: 23.34 m/s
height no air: time, speed with air: time, speed
10 m 1.43 s 14.01 m/s 1.47 s 12.84 m/s
45 m 3.03 s 29.71 m/s 3.45 s 20.91 m/s
100 m 4.51 s 44.29 m/s 5.92 s 23.02 m/s
500 m 10.10 s 99.04 m/s 23.07 s 23.34 m/s
from 10 m the air hardly matters. From 500 m it decides everything:
the ball never goes faster than about 23 m/s, however far it falls.
4 🎯 The 45 degree rule is wrong · กฎ 45 องศานั้นผิด · 45 度那条规则是错的
🇬🇧 English
Everyone is taught to throw at 45 degrees for maximum distance. With no air that is exactly right, and you can prove it with algebra: the range is v²/g and the program lands on 91.74 m against the algebra's 91.74 m.
Add air and the algebra stops being easy, so stop doing algebra. Try every angle from 20 to 65 degrees and keep the winner. That is four lines of Python, and it is a perfectly respectable way to answer a physics question.
🇹🇭 ไทย
ทุกคนถูกสอนให้ขว้างที่ 45 องศาเพื่อให้ไปได้ไกลที่สุด ถ้าไม่มีอากาศก็ถูกต้องเป๊ะ และพิสูจน์ได้ด้วยพีชคณิต ระยะทางคือ v²/g และโปรแกรมก็ได้ 91.74 เมตร เทียบกับพีชคณิตที่ได้ 91.74 เมตร
พออากาศเข้ามา พีชคณิตก็เลิกง่าย งั้นก็เลิกทำพีชคณิต ลองทุกมุมตั้งแต่ 20 ถึง 65 องศา แล้วเก็บตัวที่ชนะไว้ นั่นคือ Python สี่บรรทัด และเป็นวิธีตอบคำถามฟิสิกส์ที่น่านับถืออย่างยิ่ง
🇨🇳 中文
每个人都被教:要扔得最远就用 45 度。没有空气时这完全正确,而且可以用代数证明:射程是 v²/g,程序算出 91.74 米,代数算出 91.74 米。
加上空气,代数就不再容易了,那就别做代数。把 20 到 65 度每个角度都试一遍,留下赢家。这是四行 Python,而且是一种完全体面的回答物理问题的方式。
throw.py
"""throw.py - everyone is taught to throw at 45 degrees. Test it.
python throw.py
With no air, 45 degrees really is the best angle, and you can prove it with algebra.
With air, the algebra stops being easy, so ask the computer instead: try every angle
and see which one actually goes furthest.
"""
import math
G = 9.81
MASS = 0.057
RADIUS = 0.033
K = 0.5 * 1.2 * 0.5 * math.pi * RADIUS ** 2
SPEED = 30.0 # metres per second, a hard throw
DT = 0.0005
def distance(angle_degrees, with_air=True):
"""How far the ball lands, thrown from the ground at this angle."""
angle = math.radians(angle_degrees)
x, y = 0.0, 0.0
vx, vy = SPEED * math.cos(angle), SPEED * math.sin(angle)
while y >= 0:
speed = math.hypot(vx, vy)
if with_air:
ax = -K * speed * vx / MASS # drag always opposes the motion
ay = -G - K * speed * vy / MASS
else:
ax, ay = 0.0, -G
vx, vy = vx + ax * DT, vy + ay * DT
x, y = x + vx * DT, y + vy * DT
return x
def best_angle(with_air):
"""Try every angle and keep the winner. No algebra required."""
return max(range(20, 66), key=lambda a: distance(a, with_air))
if __name__ == "__main__":
for air in (False, True):
label = "with air" if air else "no air "
best = best_angle(air)
print(f"{label} best angle: {best} degrees, {distance(best, air):.2f} m")
print()
print(" angle no air with air")
for a in (30, 35, 40, 45, 50, 55):
print(f" {a:>3} {distance(a, False):6.2f} m {distance(a, True):6.2f} m")
print()
print("45 degrees is the right answer to a question about a world with no air.")
what it printed
no air best angle: 45 degrees, 91.74 m
with air best angle: 39 degrees, 44.29 m
angle no air with air
30 79.45 m 42.43 m
35 86.21 m 43.89 m
40 90.34 m 44.29 m
45 91.74 m 43.68 m
50 90.34 m 42.12 m
55 86.21 m 39.65 m
45 degrees is the right answer to a question about a world with no air.
5 ⏱ Where the pendulum formula gives up · จุดที่สูตรลูกตุ้มยอมแพ้ · 钟摆公式在哪里认输
🇬🇧 English
Every textbook gives the period of a pendulum as T = 2π√(L/g), then adds, usually in smaller type, “for small swings”. Notice what the formula does not contain: the angle. According to it, a pendulum pulled back 1 degree and one pulled back 90 degrees take exactly the same time.
That cannot be true, and this program measures how untrue. It integrates the real equation, the one with sin(θ) in it that nobody can solve neatly, and simply times the swing.
🇹🇭 ไทย
ตำราทุกเล่มให้คาบของลูกตุ้มเป็น T = 2π√(L/g) แล้วก็ต่อท้ายด้วยตัวอักษรเล็ก ๆ ว่า “สำหรับการแกว่งมุมเล็ก” ลองสังเกตสิ่งที่ไม่มีอยู่ในสูตร นั่นคือมุม ตามสูตรนี้ ลูกตุ้มที่ดึงไว้ 1 องศากับที่ดึงไว้ 90 องศาใช้เวลาเท่ากันเป๊ะ
นั่นเป็นจริงไม่ได้ และโปรแกรมนี้วัดว่าไม่จริงแค่ไหน มันอินทิเกรตสมการจริง สมการที่มี sin(θ) อยู่และไม่มีใครแก้ได้สวย ๆ แล้วก็แค่จับเวลาการแกว่ง
🇨🇳 中文
每本课本都把钟摆的周期写成 T = 2π√(L/g),然后用小一号的字补一句“适用于小角度摆动”。注意这个公式里没有什么:角度。按它的说法,拉开 1 度和拉开 90 度的钟摆,用的时间一模一样。
这不可能是真的,而这个程序量出了它有多不真。它积分的是真正的方程,那个带着 sin(θ)、没人能漂亮地解出来的方程,然后单纯地给摆动计时。
pendulum.py
"""pendulum.py - the pendulum formula is a lie, and you can measure how big a lie.
python pendulum.py
Every textbook gives the period of a pendulum as T = 2*pi*sqrt(L/g). Almost every
textbook then adds, quietly, "for small swings". This program measures how wrong
that formula gets as the swing grows.
"""
import math
G = 9.81
LENGTH = 1.0 # a one-metre pendulum
DT = 0.00002
def textbook_period():
"""The formula everyone memorises. It does not mention the angle at all."""
return 2 * math.pi * math.sqrt(LENGTH / G)
def measured_period(start_degrees):
"""Let it swing and time it: release from rest, wait until it comes back."""
theta = math.radians(start_degrees)
omega, t = 0.0, 0.0
# swing away from the start until it stops, that is half a period
while True:
alpha = -(G / LENGTH) * math.sin(theta) # the real equation, no shortcut
omega = omega + alpha * DT
theta = theta + omega * DT
t = t + DT
if omega >= 0 and theta <= 0: # back through the bottom, going up
break
return 2 * t
if __name__ == "__main__":
t0 = textbook_period()
print(f"a {LENGTH} m pendulum")
print(f" the textbook formula says every swing takes {t0:.4f} s,")
print(" no matter how far you pull it back. Test that.")
print()
print(" pulled back real period the formula is wrong by")
for angle in (1, 5, 10, 30, 60, 90, 120):
t = measured_period(angle)
print(f" {angle:>4} deg {t:.4f} s {100 * (t - t0) / t0:+5.2f}%")
print()
print("at small angles the formula is excellent. At 90 degrees it is out by")
print("almost a fifth, which a clock would notice within the hour.")
what it printed
a 1.0 m pendulum
the textbook formula says every swing takes 2.0061 s,
no matter how far you pull it back. Test that.
pulled back real period the formula is wrong by
1 deg 2.0061 s +0.00%
5 deg 2.0070 s +0.05%
10 deg 2.0099 s +0.19%
30 deg 2.0410 s +1.74%
60 deg 2.1529 s +7.32%
90 deg 2.3679 s +18.04%
120 deg 2.7541 s +37.29%
at small angles the formula is excellent. At 90 degrees it is out by
almost a fifth, which a clock would notice within the hour.
6 👉 What to try next · ลองอะไรต่อดี · 接下来试什么
🇬🇧 English
- Change one number. Make the tennis ball a table-tennis ball (2.7 g, 20 mm radius) and watch the terminal speed collapse. Make it a cannonball and watch the air stop mattering.
- Break the simulation on purpose. Set
DT = 0.5inpendulum.pyand watch the pendulum gain energy out of nothing. - Add something real. Chiang Mai is about 310 m above sea level, so the air is a little thinner than the 1.2 kg/m³ used here. Look up the density at 310 m and see whether it changes the best throwing angle at all.
- Check a formula you were given this week. That is the whole method: write the rule, write the reality, and print the difference.
Next: Six More Things Python Can Ask For for real data to feed these models, or Face Recognition, and its Limits for the same measuring habit applied to something less tidy. For the words to explain any of this in English, see Force Lab.
🇹🇭 ไทย
- เปลี่ยนตัวเลขเดียว เปลี่ยนลูกเทนนิสเป็นลูกปิงปอง (2.7 กรัม รัศมี 20 มม.) แล้วดูความเร็วปลายทรุดลง หรือเปลี่ยนเป็นลูกกระสุนปืนใหญ่แล้วดูอากาศหมดความสำคัญ
- ทำให้การจำลองพังโดยตั้งใจ ตั้ง
DT = 0.5ในpendulum.pyแล้วดูลูกตุ้มได้พลังงานมาจากที่ไหนไม่รู้ - ใส่ของจริงเข้าไป เชียงใหม่สูงจากระดับน้ำทะเลราว 310 เมตร อากาศจึงบางกว่า 1.2 กก./ลบ.ม. ที่ใช้ที่นี่เล็กน้อย ลองหาค่าความหนาแน่นที่ 310 เมตร แล้วดูว่ามันเปลี่ยนมุมขว้างที่ดีที่สุดหรือไม่
- ตรวจสูตรที่คุณเพิ่งได้รับมาสัปดาห์นี้ นั่นคือวิธีการทั้งหมด เขียนกฎ เขียนความจริง แล้วพิมพ์ส่วนต่างออกมา
ต่อไป: อีกหกอย่างที่ Python ขอได้ เพื่อหาข้อมูลจริงมาป้อนโมเดลเหล่านี้ หรือ การรู้จำใบหน้าและขีดจำกัดของมัน เพื่อดูนิสัยการวัดแบบเดียวกันกับเรื่องที่เรียบร้อยน้อยกว่า ถ้าอยากได้คำศัพท์ภาษาอังกฤษไว้อธิบายเรื่องพวกนี้ ดูที่ Force Lab
🇨🇳 中文
- 只改一个数字。把网球换成乒乓球(2.7 克,半径 20 毫米),看终端速度怎么垮下来。换成炮弹,再看空气怎么变得无关紧要。
- 故意把模拟弄坏。把
pendulum.py里的DT设成0.5,看钟摆凭空多出能量来。 - 加一点真实世界进去。清迈海拔约 310 米,空气比这里用的 1.2 kg/m³ 稍薄。查一下 310 米处的空气密度,看看它到底会不会改变最佳投掷角。
- 去检查你这周刚学到的某个公式。整套方法就是这样:写下规则,写下现实,然后把差值打印出来。
接下来:想找真实数据来喂这些模型,看 Python 还能要来的六样东西;想看同一种测量习惯用在更不整齐的东西上,看 人脸识别,以及它的极限。想要用英文讲清楚这些内容的词汇,看 Force Lab。