Obliczanie prędkości ucieczki w Pythonie - Naucz się obliczać minimalną prędkość potrzebną do wyrwania się z grawitacji planety używając Pythona. Zbudujemy kompletny kalkulator działający dla dowolnego ciała niebieskiego, od prostych wzorów po interaktywny program z bazą planet.

Obliczanie prędkości ucieczki w Pythonie

Wyobraź sobie, że rzucasz piłkę w górę. Zawsze spada z powrotem, prawda? A co, gdybyś rzucił ją tak mocno, że nigdy by nie wróciła? To właśnie jest prędkość ucieczki - minimalna prędkość potrzebna do wyrwania się z grawitacji planety. Dziś napiszemy program, który obliczy tę prędkość dla dowolnego ciała niebieskiego używając NumPy - potężnej biblioteki Pythona do obliczeń naukowych.

Dlaczego NumPy zamiast zwykłego Pythona?

Choć wbudowane funkcje matematyczne Pythona działają dobrze dla prostych obliczeń, NumPy oferuje kilka zalet dla obliczeń naukowych:

  • Większa wydajność dla obliczeń na dużą skalę
  • Lepsza stabilność numeryczna i kontrola precyzji
  • Operacje wektorowe - obliczanie dla wielu planet jednocześnie
  • Standard branżowy dla naukowego Pythona

Najpierw zainstalujmy NumPy (jeśli jeszcze nie masz):

pip install numpy

Zrozumienie problemu

Zanim zaczniemy kodować, zastanówmy się, co właściwie musimy zrobić:

  1. Znamy wzór fizyczny: v = √(2GM/r)
  2. Potrzebujemy danych wejściowych: masa planety i jej promień
  3. Musimy wykonać obliczenia matematyczne
  4. Wyświetlimy wynik w czytelnej formie

Brzmi prosto? Bo tak właśnie jest. Ale najpierw musimy zrozumieć jeden ważny koncept używany w obliczeniach astronomicznych.

Notacja naukowa - sposób na ogromne liczby

Masa Ziemi to około 5 972 000 000 000 000 000 000 000 kilogramów. Niewygodne do zapisania, prawda? Dlatego w nauce używamy notacji naukowej:

5.972 × 10²⁴ kg

W Pythonie zapisujemy to jako 5.972e24, gdzie:

  • 5.972 to mantysa (główna liczba)
  • e oznacza "razy 10 do potęgi"
  • 24 to wykładnik (o ile miejsc przesuwamy przecinek)

Kilka przykładów z NumPy:

import numpy as np

# Notacja naukowa w NumPy
earth_mass = np.float64(5.972e24)      # 5.972 × 10²⁴
earth_radius = np.float64(6.371e6)     # 6.371 × 10⁶ (6 371 000 metrów)
gravity_constant = np.float64(6.674e-11)  # 6.674 × 10⁻¹¹ (bardzo mała liczba)

# NumPy efektywnie obsługuje te liczby
print(f"Masa Ziemi: {earth_mass}")  # Wyświetli: 5.972e+24
print(f"To jest: {earth_mass:,.0f}")  # Wyświetli z wszystkimi zerami

Uwaga: Wyświetlona liczba może nie pokazywać dokładnych zer na końcu ze względu na precyzję zmiennoprzecinkową, ale float64 NumPy zapewnia doskonałą dokładność dla naszych obliczeń.

Rozbijamy problem na kroki

Teraz, gdy rozumiemy notację, rozpiszmy nasze rozwiązanie krok po kroku:

Krok 1: Zdefiniuj stałe i dane

Najpierw określmy, co wiemy:

import numpy as np

# Stała grawitacyjna - zawsze taka sama we wszechświecie
G = np.float64(6.67430e-11)  # m³ kg⁻¹ s⁻²

# Dane dla Ziemi (jako przykład)
earth_mass = np.float64(5.972e24)  # kilogramy
earth_radius = np.float64(6.371e6)  # metry (6371 km)

Krok 2: Zastosuj wzór

Teraz podstawmy do wzoru v = √(2GM/r):

# Obliczenie krok po kroku
numerator = 2 * G * earth_mass
denominator = earth_radius
division_result = numerator / denominator
escape_velocity = np.sqrt(division_result)

print(f"Prędkość ucieczki: {escape_velocity:.0f} m/s")

Krok 3: Uprość kod

Gdy już rozumiemy każdy krok, możemy zapisać to krócej:

import numpy as np

G = np.float64(6.67430e-11)
earth_mass = np.float64(5.972e24)
earth_radius = np.float64(6.371e6)

escape_velocity = np.sqrt(2 * G * earth_mass / earth_radius)
print(f"Prędkość ucieczki z Ziemi: {escape_velocity/1000:.1f} km/s")

Wersja 1: Funkcja do wielokrotnego użytku

Zamiast kopiować kod dla każdej planety, stwórzmy funkcję:

import numpy as np

def calculate_escape_velocity(mass, radius):
    """
    Oblicza prędkość ucieczki dla dowolnego ciała niebieskiego.
    
    Parametry:
        mass: masa w kilogramach
        radius: promień w metrach
    
    Zwraca:
        prędkość ucieczki w m/s
    """
    G = np.float64(6.67430e-11)
    return np.sqrt(2 * G * mass / radius)

# Testujemy dla różnych planet
print("PRĘDKOŚCI UCIECZKI W UKŁADZIE SŁONECZNYM")
print("-" * 40)

# Ziemia
v = calculate_escape_velocity(5.972e24, 6.371e6)
print(f"Ziemia: {v/1000:.1f} km/s")

# Mars
v = calculate_escape_velocity(6.417e23, 3.3895e6)
print(f"Mars: {v/1000:.1f} km/s")

# Księżyc
v = calculate_escape_velocity(7.342e22, 1.7374e6)
print(f"Księżyc: {v/1000:.1f} km/s")

Wersja 2: Program z bazą planet

Teraz stwórzmy bardziej użyteczny program z gotową bazą danych. NumPy naprawdę błyszczy tutaj z operacjami wektorowymi:

import numpy as np

# Słownik z danymi planet
planets = {
    "Merkury": {"mass": 3.301e23, "radius": 2.4397e6},
    "Wenus": {"mass": 4.867e24, "radius": 6.0518e6},
    "Ziemia": {"mass": 5.972e24, "radius": 6.371e6},
    "Mars": {"mass": 6.417e23, "radius": 3.3895e6},
    "Jowisz": {"mass": 1.898e27, "radius": 6.9911e7},
    "Saturn": {"mass": 5.683e26, "radius": 5.8232e7},
    "Uran": {"mass": 8.681e25, "radius": 2.5362e7},
    "Neptun": {"mass": 1.024e26, "radius": 2.4622e7},
    "Księżyc": {"mass": 7.342e22, "radius": 1.7374e6}
}

def calculate_escape_velocity(mass, radius):
    G = np.float64(6.67430e-11)
    return np.sqrt(2 * G * mass / radius)

def show_planet_data(name, data):
    """Wyświetla dane planety i jej prędkość ucieczki."""
    v_escape = calculate_escape_velocity(data["mass"], data["radius"])
    
    print(f"\n{name}:")
    print(f"  Masa: {data['mass']:.2e} kg")
    print(f"  Promień: {data['radius']/1000:.0f} km")
    print(f"  Prędkość ucieczki: {v_escape:.0f} m/s ({v_escape/1000:.1f} km/s)")

# Wyświetlamy dane dla wszystkich planet
print("="*50)
print("PRĘDKOŚCI UCIECZKI W UKŁADZIE SŁONECZNYM")
print("="*50)

for planet_name, planet_data in planets.items():
    show_planet_data(planet_name, planet_data)

# Bonus: Oblicz wszystko naraz używając tablic NumPy!
print("\n" + "="*50)
print("OBLICZENIA WEKTOROWE Z NUMPY")
print("="*50)

names = list(planets.keys())
masses = np.array([planets[p]["mass"] for p in names])
radii = np.array([planets[p]["radius"] for p in names])

# Oblicz wszystkie prędkości ucieczki naraz
G = np.float64(6.67430e-11)
all_velocities = np.sqrt(2 * G * masses / radii)

for i, name in enumerate(names):
    print(f"{name}: {all_velocities[i]/1000:.1f} km/s")

Wersja 3: Interaktywny kalkulator

Teraz najciekawsza część - program, który pozwala użytkownikom wybierać planety lub wprowadzać własne dane:

import numpy as np

# Baza danych planet
planets_db = {
    "1": {"name": "Merkury", "mass": 3.301e23, "radius": 2.4397e6},
    "2": {"name": "Wenus", "mass": 4.867e24, "radius": 6.0518e6},
    "3": {"name": "Ziemia", "mass": 5.972e24, "radius": 6.371e6},
    "4": {"name": "Mars", "mass": 6.417e23, "radius": 3.3895e6},
    "5": {"name": "Jowisz", "mass": 1.898e27, "radius": 6.9911e7},
    "6": {"name": "Saturn", "mass": 5.683e26, "radius": 5.8232e7},
    "7": {"name": "Uran", "mass": 8.681e25, "radius": 2.5362e7},
    "8": {"name": "Neptun", "mass": 1.024e26, "radius": 2.4622e7},
    "9": {"name": "Księżyc", "mass": 7.342e22, "radius": 1.7374e6}
}

def calculate_escape_velocity(mass, radius):
    """Oblicza prędkość ucieczki używając NumPy."""
    G = np.float64(6.67430e-11)
    mass = np.float64(mass)
    radius = np.float64(radius)
    return np.sqrt(2 * G * mass / radius)

def display_menu():
    """Wyświetla menu wyboru."""
    print("\n" + "="*50)
    print("KALKULATOR PRĘDKOŚCI UCIECZKI (Edycja NumPy)")
    print("="*50)
    print("\nWybierz planetę:")
    
    for key, planet in planets_db.items():
        print(f"  {key}. {planet['name']}")
    
    print("\n  10. Wprowadź własne parametry")
    print("  0. Wyjście")
    print("-"*50)

def get_custom_parameters():
    """Pobiera parametry od użytkownika."""
    print("\nWPROWADŹ DANE CIAŁA NIEBIESKIEGO")
    
    name = input("Nazwa: ")
    
    while True:
        try:
            mass_str = input("Masa w kg (np. 5.972e24): ")
            mass = float(mass_str)
            if mass <= 0:
                print("Masa musi być dodatnia!")
                continue
            break
        except ValueError:
            print("Nieprawidłowa wartość! Spróbuj ponownie.")
    
    while True:
        try:
            radius_str = input("Promień w km: ")
            radius = float(radius_str) * 1000  # konwersja na metry
            if radius <= 0:
                print("Promień musi być dodatni!")
                continue
            break
        except ValueError:
            print("Nieprawidłowa wartość! Spróbuj ponownie.")
    
    return name, mass, radius

def display_results(name, mass, radius):
    """Wyświetla wyniki obliczeń."""
    v_escape = calculate_escape_velocity(mass, radius)
    
    print(f"\n{'='*50}")
    print(f"WYNIKI DLA: {name}")
    print(f"{'='*50}")
    print(f"Masa: {mass:.2e} kg")
    print(f"Promień: {radius/1000:,.0f} km")
    print(f"\nPrędkość ucieczki:")
    
    # Lepsze obsługiwanie bardzo małych wartości
    if v_escape < 0.01:
        print(f"  → {v_escape:.2e} m/s")
    else:
        print(f"  → {v_escape:,.0f} m/s")
        print(f"  → {v_escape/1000:.2f} km/s")
    
    # Porównanie z Ziemią
    earth_v = calculate_escape_velocity(5.972e24, 6.371e6)
    if name.lower() != "ziemia":
        ratio = v_escape / earth_v
        print(f"\nPorównanie z Ziemią: {ratio:.2f}x")

def main():
    """Główna pętla programu."""
    print("Witaj w kalkulatorze prędkości ucieczki!")
    print("Napędzany przez NumPy dla dokładnych obliczeń naukowych")
    
    while True:
        display_menu()
        choice = input("\nTwój wybór: ")
        
        if choice == "0":
            print("\nDo zobaczenia! ?")
            break
        elif choice in planets_db:
            planet = planets_db[choice]
            display_results(planet["name"], planet["mass"], planet["radius"])
        elif choice == "10":
            name, mass, radius = get_custom_parameters()
            display_results(name, mass, radius)
        else:
            print("\nNieprawidłowy wybór!")
        
        input("\nNaciśnij Enter aby kontynuować...")

# Uruchomienie programu
if __name__ == "__main__":
    main()

Przykład użycia dla nieznanej planety

Załóżmy, że odkryto nową egzoplanetę. Możesz użyć opcji "własne parametry" i wprowadzić:

  • Nazwa: Kepler-452b
  • Masa: 3.0e25 kg (5 razy masa Ziemi)
  • Promień: 9556 km (1.5 raza promień Ziemi)

Program obliczy prędkość ucieczki i porówna ją z Ziemią. To świetny sposób na eksplorowanie hipotetycznych scenariuszy!

Moc NumPy: Obliczenia wsadowe

Jedną z supermocy NumPy jest obliczanie dla wielu obiektów naraz:

import numpy as np

# Oblicz prędkości ucieczki dla wielu ciał naraz
names = np.array(['Mała Asteroida', 'Duża Asteroida', 'Rozmiar Księżyca'])
masses = np.array([1e15, 1e18, 1e22])  # kg
radii = np.array([10000, 100000, 1000000])  # metry

G = np.float64(6.67430e-11)
velocities = np.sqrt(2 * G * masses / radii)

print("Wyniki obliczeń wsadowych:")
for i in range(len(names)):
    print(f"{names[i]}: {velocities[i]:.2f} m/s")

Co dalej?

Teraz, gdy masz działający kalkulator z NumPy, możesz go rozbudować:

  1. Dodaj więcej obiektów: asteroidy, komety, gwiazdy
  2. Oblicz prędkość orbitalną: to prędkość ucieczki podzielona przez √2
  3. Przetwarzaj pliki CSV: wczytuj dane planet z plików używając NumPy
  4. Twórz wizualizacje: wykreśl prędkości ucieczki z matplotlib
  5. Symuluj trajektorie: użyj tablic NumPy do mechaniki orbitalnej

Podsumowanie

Przeszliśmy od prostego wzoru do pełnoprawnego kalkulatora używającego NumPy. Po drodze nauczyłeś się:

  • Dlaczego NumPy jest preferowany do obliczeń naukowych
  • Jak używać notacji naukowej w Pythonie
  • Jak tworzyć funkcje wielokrotnego użytku
  • Jak wykonywać obliczenia wektorowe na wielu obiektach
  • Jak budować interaktywne programy naukowe

Pamiętaj - NumPy to fundament naukowego Pythona. Opanuj go, a będziesz gotowy na bardziej zaawansowane biblioteki jak SciPy, Pandas i Matplotlib.

Powodzenia w obliczaniu prędkości ucieczki z różnych światów!

import numpy as np

# Baza danych planet
planets_db = {
    "1": {"name": "Merkury", "mass": 3.301e23, "radius": 2.4397e6},
    "2": {"name": "Wenus", "mass": 4.867e24, "radius": 6.0518e6},
    "3": {"name": "Ziemia", "mass": 5.972e24, "radius": 6.371e6},
    "4": {"name": "Mars", "mass": 6.417e23, "radius": 3.3895e6},
    "5": {"name": "Jowisz", "mass": 1.898e27, "radius": 6.9911e7},
    "6": {"name": "Saturn", "mass": 5.683e26, "radius": 5.8232e7},
    "7": {"name": "Uran", "mass": 8.681e25, "radius": 2.5362e7},
    "8": {"name": "Neptun", "mass": 1.024e26, "radius": 2.4622e7},
    "9": {"name": "Księżyc", "mass": 7.342e22, "radius": 1.7374e6}
}

def calculate_escape_velocity(mass, radius):
    """Oblicza prędkość ucieczki używając NumPy."""
    G = np.float64(6.67430e-11)
    mass = np.float64(mass)
    radius = np.float64(radius)
    return np.sqrt(2 * G * mass / radius)

def display_menu():
    """Wyświetla menu wyboru."""
    print("\n" + "="*50)
    print("KALKULATOR PRĘDKOŚCI UCIECZKI (Edycja NumPy)")
    print("="*50)
    print("\nWybierz planetę:")
    
    for key, planet in planets_db.items():
        print(f"  {key}. {planet['name']}")
    
    print("\n  10. Wprowadź własne parametry")
    print("  0. Wyjście")
    print("-"*50)

def get_custom_parameters():
    """Pobiera parametry od użytkownika."""
    print("\nWPROWADŹ DANE CIAŁA NIEBIESKIEGO")
    
    name = input("Nazwa: ")
    
    while True:
        try:
            mass_str = input("Masa w kg (np. 5.972e24): ")
            mass = float(mass_str)
            if mass <= 0:
                print("Masa musi być dodatnia!")
                continue
            break
        except ValueError:
            print("Nieprawidłowa wartość! Spróbuj ponownie.")
    
    while True:
        try:
            radius_str = input("Promień w km: ")
            radius = float(radius_str) * 1000  # konwersja na metry
            if radius <= 0:
                print("Promień musi być dodatni!")
                continue
            break
        except ValueError:
            print("Nieprawidłowa wartość! Spróbuj ponownie.")
    
    return name, mass, radius

def display_results(name, mass, radius):
    """Wyświetla wyniki obliczeń."""
    v_escape = calculate_escape_velocity(mass, radius)
    
    print(f"\n{'='*50}")
    print(f"WYNIKI DLA: {name}")
    print(f"{'='*50}")
    print(f"Masa: {mass:.2e} kg")
    print(f"Promień: {radius/1000:,.0f} km")
    print(f"\nPrędkość ucieczki:")
    
    # Lepsze obsługiwanie bardzo małych wartości
    if v_escape < 0.01:
        print(f"  → {v_escape:.2e} m/s")
    else:
        print(f"  → {v_escape:,.0f} m/s")
        print(f"  → {v_escape/1000:.2f} km/s")
    
    # Porównanie z Ziemią
    earth_v = calculate_escape_velocity(5.972e24, 6.371e6)
    if name.lower() != "ziemia":
        ratio = v_escape / earth_v
        print(f"\nPorównanie z Ziemią: {ratio:.2f}x")

def main():
    """Główna pętla programu."""
    print("Witaj w kalkulatorze prędkości ucieczki!")
    print("Napędzany przez NumPy dla dokładnych obliczeń naukowych")
    
    while True:
        display_menu()
        choice = input("\nTwój wybór: ")
        
        if choice == "0":
            print("\nDo zobaczenia! ?")
            break
        elif choice in planets_db:
            planet = planets_db[choice]
            display_results(planet["name"], planet["mass"], planet["radius"])
        elif choice == "10":
            name, mass, radius = get_custom_parameters()
            display_results(name, mass, radius)
        else:
            print("\nNieprawidłowy wybór!")
        
        input("\nNaciśnij Enter aby kontynuować...")

# Uruchomienie programu
if __name__ == "__main__":
    main()