🇵🇱 Zapis słowny liczb

WPROWADZENIE

Czy zastanawialiście się kiedyś, jak ułatwić dziecku naukę ortografii i matematyki jednocześnie? Pisanie dużych liczb słownie to jedno z największych wyzwań, przed którymi stają uczniowie szkół podstawowych. W odpowiedzi na te trudności powstała aplikacja. To intuicyjne, interaktywne narzędzie, które w ułamku sekundy zamienia dowolną liczbę zapisaną cyframi (aż do miliardów!) na jej poprawną formę słowną. Dzięki przyjaznemu designowi i prostocie obsługi, zamienia nudne ćwiczenia w cyfrową zabawę.

Pomysły na zastosowanie

Program nauczania matematyki w 4 klasie kładzie duży nacisk na biegłość w posługiwaniu się dużymi liczbami w systemie dziesiątkowym. Oto jak aplikacja pomaga w szkole:

  • Nauka poprawnej pisowni: Dzieci często mylą „dwadzieścia” z „dwadzieścia”, czy mają problem z pisownią liczebników takich jak „dziewięćset”. Aplikacja służy jako wzorzec ortograficzny.
  • Wielkie liczby (miliardy): W 4 klasie uczniowie wychodzą poza zakres tysięcy. Program pozwala im „zobaczyć” strukturę milionów i miliardów, co ułatwia zrozumienie rzędów wielkości.
  • Samokontrola: Uczeń może najpierw spróbować zapisać liczbę samodzielnie w zeszycie, a następnie sprawdzić wynik w aplikacji. To buduje pewność siebie i promuje samodzielność w nauce.
  • Zadania praktyczne: Aplikacja jest nieoceniona przy nauce wypisywania druków pocztowych, czeków czy innych dokumentów, gdzie wymagany jest zapis słowny kwot.

APLIKACJA W HTML

Otwórz w nowym oknie

Zobacz kod w języku HTML:

Rozwiń
<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Magiczny zapis liczb - Klasa 4+</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@400;600;700&display=swap" rel="stylesheet">
    <style>
        body {
            font-family: 'Quicksand', sans-serif;
            background: linear-gradient(135deg, #6EE7B7 0%, #3B82F6 100%);
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 20px;
        }
        .glass {
            background: rgba(255, 255, 255, 0.95);
            backdrop-filter: blur(10px);
            border-radius: 2rem;
            box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
        }
        .floating {
            animation: floating 3s ease-in-out infinite;
        }
        @keyframes floating {
            0% { transform: translateY(0px); }
            50% { transform: translateY(-10px); }
            100% { transform: translateY(0px); }
        }
        /* Ukrycie strzałek w polach typu number (na wypadek powrotu do tego typu) */
        input::-webkit-outer-spin-button,
        input::-webkit-inner-spin-button {
            -webkit-appearance: none;
            margin: 0;
        }
    </style>
</head>
<body>

    <div class="glass max-w-2xl w-full p-8 md:p-12 text-center relative overflow-hidden">
        <!-- Elementy dekoracyjne -->
        <div class="absolute -top-10 -left-10 w-32 h-32 bg-yellow-300 rounded-full opacity-50 floating"></div>
        <div class="absolute -bottom-10 -right-10 w-40 h-40 bg-pink-300 rounded-full opacity-50 floating" style="animation-delay: 1s;"></div>

        <header class="relative z-10">
            <h1 class="text-4xl md:text-5xl font-bold text-blue-600 mb-2">🔢 Zapis słowny liczb</h1>
            <p class="text-gray-600 text-lg mb-2">Wpisz liczbę, a ja napiszę ją słownie!</p>
            <p class="text-blue-500 font-bold bg-blue-50 inline-block px-4 py-1 rounded-full text-sm mb-8 border border-blue-100">
                ✨ Tylko cyfry • Max 12 znaków
            </p>
        </header>

        <main class="relative z-10 space-y-6">
            <div class="group">
                <input 
                    type="text" 
                    id="numberInput" 
                    inputmode="numeric"
                    placeholder="Wpisz tylko cyfry..."
                    class="w-full text-3xl p-4 border-4 border-blue-200 rounded-2xl focus:border-yellow-400 focus:outline-none transition-all text-center font-bold text-blue-800"
                    oninput="validateInput(this)"
                >
            </div>

            <button 
                onclick="convertNumber()"
                class="w-full bg-yellow-400 hover:bg-yellow-500 text-blue-900 font-bold text-xl py-4 rounded-2xl shadow-lg transform transition-transform active:scale-95"
            >
                ✨ Zamień na słowa ✨
            </button>

            <div id="resultContainer" class="hidden mt-8 p-6 bg-blue-50 rounded-2xl border-2 border-dashed border-blue-300">
                <p class="text-sm text-blue-400 uppercase tracking-widest font-bold mb-2">Twój zapis to:</p>
                <div id="resultText" class="text-2xl md:text-3xl text-blue-900 font-semibold leading-snug"></div>
                
                <button 
                    onclick="copyToClipboard()"
                    class="mt-4 text-sm bg-white hover:bg-gray-100 text-gray-600 py-1 px-4 rounded-full border border-gray-200 transition-colors"
                >
                    📋 Kopiuj zapis
                </button>
            </div>
        </main>

        <footer class="mt-12 text-gray-400 text-sm">
            Idealne dla uczniów klasy 4! 🏫
        </footer>
    </div>

    <script>
        const jednostki = ["", "jeden", "dwa", "trzy", "cztery", "pięć", "sześć", "siedem", "osiem", "dziewięć"];
        const nastki = ["dziesięć", "jedenaście", "dwanaście", "trzynaście", "czternaście", "piętnaście", "szesnaście", "siedemnaście", "osiemnaście", "dziewiętnaście"];
        const dziesiatki = ["", "dziesięć", "dwadzieścia", "trzydzieści", "czterdzieści", "pięćdziesiąt", "sześćdziesiąt", "siedemdziesiąt", "osiemdziesiąt", "dziewięćdziesiąt"];
        const setki = ["", "sto", "dwieście", "trzysta", "czterysta", "pięćset", "sześćset", "siedemset", "osiemset", "dziewięćset"];
        const grupy = [
            ["", "", ""],
            ["tysiąc", "tysiące", "tysięcy"],
            ["milion", "miliony", "milionów"],
            ["miliard", "miliardy", "miliardów"]
        ];

        // Funkcja pilnująca, aby wpisywano tylko cyfry
        function validateInput(el) {
            // Usuń wszystko co nie jest cyfrą
            let val = el.value.replace(/\D/g, '');
            // Ogranicz do 12 znaków
            if (val.length > 12) {
                val = val.slice(0, 12);
            }
            el.value = val;
        }

        function odmien(n, formy) {
            if (n === 1) return formy[0];
            const n10 = n % 10;
            const n100 = n % 100;
            if (n10 > 1 && n10 < 5 && (n100 < 10 || n100 > 20)) return formy[1];
            return formy[2];
        }

        function liczbaNaSlowa(n) {
            if (n === 0) return "zero";
            
            // Konwersja BigInt dla bezpieczeństwa przy 12 cyfrach
            let bigN = BigInt(n);
            let wynik = [];
            let grupaIdx = 0;

            while (bigN > 0n) {
                let czesc = Number(bigN % 1000n);
                if (czesc > 0) {
                    let czescSlowami = [];
                    let s = Math.floor(czesc / 100);
                    let d = Math.floor((czesc % 100) / 10);
                    let j = czesc % 10;

                    if (s > 0) czescSlowami.push(setki[s]);

                    if (d === 1) {
                        czescSlowami.push(nastki[j]);
                    } else {
                        if (d > 0) czescSlowami.push(dziesiatki[d]);
                        if (j > 0) {
                            if (!(j === 1 && s === 0 && d === 0 && grupaIdx > 0)) {
                                czescSlowami.push(jednostki[j]);
                            }
                        }
                    }

                    if (grupaIdx > 0) {
                        czescSlowami.push(odmien(czesc, grupy[grupaIdx]));
                    }

                    wynik.unshift(czescSlowami.join(" "));
                }
                bigN = bigN / 1000n;
                grupaIdx++;
            }

            return wynik.join(" ").trim();
        }

        function convertNumber() {
            const input = document.getElementById('numberInput');
            const resultContainer = document.getElementById('resultContainer');
            const resultText = document.getElementById('resultText');
            
            if (input.value === "") {
                showToast("Najpierw wpisz jakąś liczbę!");
                return;
            }

            // Przetwarzamy jako tekst, by nie stracić precyzji przy dużych liczbach
            const slownie = liczbaNaSlowa(input.value);
            
            resultContainer.classList.remove('hidden');
            resultText.innerText = slownie;
            
            resultContainer.style.opacity = 0;
            resultContainer.style.transform = "translateY(20px)";
            setTimeout(() => {
                resultContainer.style.transition = "all 0.5s ease";
                resultContainer.style.opacity = 1;
                resultContainer.style.transform = "translateY(0)";
            }, 10);
        }

        function copyToClipboard() {
            const text = document.getElementById('resultText').innerText;
            const tempInput = document.createElement("input");
            tempInput.value = text;
            document.body.appendChild(tempInput);
            tempInput.select();
            document.execCommand("copy");
            document.body.removeChild(tempInput);
            showToast("Skopiowano do schowka! ✅");
        }

        function showToast(msg) {
            const toast = document.createElement("div");
            toast.className = "fixed bottom-5 left-1/2 transform -translate-x-1/2 bg-blue-600 text-white px-6 py-3 rounded-full shadow-2xl z-50 transition-all opacity-0";
            toast.innerText = msg;
            document.body.appendChild(toast);
            
            setTimeout(() => toast.style.opacity = "1", 10);
            setTimeout(() => {
                toast.style.opacity = "0";
                setTimeout(() => document.body.removeChild(toast), 500);
            }, 2500);
        }

        document.getElementById('numberInput').addEventListener('keypress', function (e) {
            if (e.key === 'Enter') {
                convertNumber();
            }
        });
    </script>
</body>
</html>

KOD W JĘZYKU PYTHON

def odmien(n, formy):
    if n == 1:
        return formy[0]
    n10 = n % 10
    n100 = n % 100
    if 1 < n10 < 5 and (n100 < 10 or n100 > 20):
        return formy[1]
    return formy[2]

def liczba_na_slowa(n):
    if n == 0:
        return "zero"

    jednostki = ["", "jeden", "dwa", "trzy", "cztery", "pięć", "sześć", "siedem", "osiem", "dziewięć"]
    nastki = ["dziesięć", "jedenaście", "dwanaście", "trzynaście", "czternaście", "piętnaście", "szesnaście", "siedemnaście", "osiemnaście", "dziewiętnaście"]
    dziesiatki = ["", "dziesięć", "dwadzieścia", "trzydzieści", "czterdzieści", "pięćdziesiąt", "sześćdziesiąt", "siedemdziesiąt", "osiemdziesiąt", "dziewięćdziesiąt"]
    setki = ["", "sto", "dwieście", "trzysta", "czterysta", "pięćset", "sześćset", "siedemset", "osiemset", "dziewięćset"]
    grupy = [
        ["", "", ""],
        ["tysiąc", "tysiące", "tysięcy"],
        ["milion", "miliony", "milionów"],
        ["miliard", "miliardy", "miliardów"]
    ]

    wynik = []
    grupa_idx = 0
    temp_n = n

    while temp_n > 0:
        czesc = temp_n % 1000
        if czesc > 0:
            czesc_slowami = []
            s = czesc // 100
            d = (czesc % 100) // 10
            j = czesc % 10

            if s > 0:
                czesc_slowami.append(setki[s])

            if d == 1:
                czesc_slowami.append(nastki[j])
            else:
                if d > 0:
                    czesc_slowami.append(dziesiatki[d])
                if j > 0:
                    # Specjalny przypadek dla "tysiąc" zamiast "jeden tysiąc"
                    if not (j == 1 and s == 0 and d == 0 and grupa_idx > 0):
                        czesc_slowami.append(jednostki[j])

            if grupa_idx > 0:
                czesc_slowami.append(odmien(czesc, grupy[grupa_idx]))

            wynik.insert(0, " ".join(czesc_slowami))
        
        temp_n //= 1000
        grupa_idx += 1

    return " ".join(wynik).strip()

# Interfejs użytkownika w konsoli
print("=== Magiczny Zapis Liczb ===")
while True:
    wejscie = input("\nWpisz liczbę (max 12 cyfr) lub 'q' aby wyjść: ").strip()
    if wejscie.lower() == 'q':
        break
    
    if not wejscie.isdigit() or len(wejscie) > 12:
        print("Błąd: Wpisz tylko cyfry (maksymalnie 12).")
        continue

    wynik = liczba_na_slowa(int(wejscie))
    print(f"Zapis słowny: {wynik}")

⬆️⬆️⬆️ Zobacz w Google Colaboratory


JAK DZIAŁA PROGRAM?

Działanie programu można podzielić na cztery kluczowe etapy: Algorytm programu opiera się na sposobie, w jaki naturalnie czytamy liczby – dzieląc je na grupy trzycyfrowe.

Krok 1: Przechowywanie słów (Słowniki danych)

Na początku definiujemy listy zawierające polskie nazwy:

  • Jednostki, nastki, dziesiątki i setki (np. „dwa”, „dwanaście”, „dwadzieścia”, „dwieście”).
  • Grupy wielkości (tysiące, miliony, miliardy) wraz z ich odmianami.

Krok 2: Mechanizm odmiany

Język polski jest trudny! Mówimy „1 milion”, ale „2 miliony” i „5 milionów”. Funkcja odmien sprawdza ostatnią cyfrę liczby, aby zdecydować, którą formę z listy wybrać:

  • Forma 0: (tysiąc) – dla n = 1.
  • Forma 1: (tysiące) – dla n kończących się na 2, 3, 4 (poza 12-14).
  • Forma 2: (tysięcy) – dla pozostałych (5-9, 10-19, 0).

Krok 3: Dzielenie liczby na „trójki”

Program bierze liczbę i w pętli while odcina z niej ostatnie 3 cyfry (używając modulo % 1000). Te trzy cyfry są przetwarzane jako oddzielna mała liczba (od 0 do 999).

Krok 4: Analiza trójki (Setki, Dziesiątki, Jednostki)

Dla każdej grupy trzech cyfr program oblicza:

  1. Ile jest setek (dzielenie całkowite przez 100).
  2. Czy występuje nastka (jeśli cyfra dziesiątek to 1).
  3. Jeśli nie ma nastki – ile jest dziesiątek i jednostek.

Krok 5: Składanie wszystkiego w całość

Program dodaje nazwę grupy (np. „tysięcy”) po przetworzeniu każdej trójki, a następnie łączy wszystkie fragmenty w jeden długi tekst za pomocą funkcji join. Jeśli wpiszesz „1234”, program zobaczy „1” (tysiąc) oraz „234” (dwieście trzydzieści cztery) i połączy to w całość.

Leave a Reply

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *