Wymuszanie i konwersja typów
Proszę poznać automatyczne wymuszanie konwersji między ciągami znaków a liczbami oraz jawne użycie tonumber/tostring.
Wymuszanie i konwersja typów to bezpłatna lekcja Lua Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Lua Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Lua Academy zawiera 4 lekcji w sumie.
Czym jest wymuszanie konwersji typów?
Wymuszanie konwersji typów to automatyczna konwersja wartości z jednego typu na inny, gdy wymaga tego kontekst. Lua wykonuje konwersję w dwóch określonych kierunkach: z ciągu znaków na liczbę w kontekstach arytmetycznych oraz z liczby na ciąg znaków w kontekstach konkatenacji.
W przeciwieństwie do JavaScriptu konwersja typów w Lua jest ograniczona i przewidywalna. Lua nie konwertuje automatycznie wartości logicznych na liczby ani tabel na ciągi znaków.
-- String to number (arithmetic context)
print("10" + 5) -- 15 (coerced)
print("3.14" * 2) -- 6.28
-- Number to string (concatenation context)
print(10 .. "px") -- 10px
print(3.14 .. "!") -- 3.14!
-- No boolean coercion
-- print(true + 1) -- ERROR!Reguły konwersji z ciągu znaków na liczbę
Gdy ciąg znaków pojawia się w wyrażeniu arytmetycznym, Lua próbuje przekonwertować go na liczbę. Jeśli ciąg nie reprezentuje prawidłowej liczby, zgłaszany jest błąd wykonania. Prawidłowe ciągi liczbowe obejmują liczby całkowite ("42"), zmiennoprzecinkowe ("3.14"), szesnastkowe ("0xff") oraz zapis wykładniczy ("1e3").
Ciągi ze spacjami na początku lub końcu są akceptowane — Lua usuwa te spacje podczas konwersji.
print("42" + 0) -- 42 (integer)
print("3.14" + 0) -- 3.14 (float)
print("0xff" + 0) -- 255 (hex)
print(" 10 " + 0) -- 10 (whitespace ok)
print("1e3" + 0) -- 1000.0
-- This will error:
-- print("hello" + 0) -- attempt to perform arithmetic on a string valueKonwersja liczby na ciąg znaków
Podczas konkatenacji liczby za pomocą .. Lua automatycznie konwertuje liczbę na ciąg znaków. Liczby całkowite są zapisywane w systemie dziesiętnym, a liczby zmiennoprzecinkowe mogą zyskać miejsca po przecinku. Aby precyzyjnie kontrolować format, należy zawsze używać tostring() lub string.format(), zamiast polegać na niejawnej konwersji.
print(10 .. "!") -- 10!
print(3.14 .. "!") -- 3.14!
print(1/3 .. "!") -- 0.33333333333333!
-- Explicit is better for precision
print(string.format("%.2f", 1/3)) -- 0.33
print(tostring(10)) -- 10
print(tostring(10.0)) -- 10.0tonumber(): jawna konwersja
tonumber(v) jawnie konwertuje wartość na liczbę. Po pomyślnej konwersji zwraca otrzymaną liczbę, a jeśli konwersja się nie powiedzie, zwraca nil — nigdy nie zgłasza błędu. Opcjonalnie można podać podstawę systemu (2–36) do analizy liczb całkowitych, co umożliwia konwersję liczb binarnych, ósemkowych i szesnastkowych.
Podczas przetwarzania danych wprowadzanych przez użytkownika należy zawsze sprawdzać, czy wartość zwrócona przez tonumber() nie jest równa nil.
print(tonumber("42")) -- 42
print(tonumber("3.14")) -- 3.14
print(tonumber("0xFF")) -- 255
print(tonumber("hello")) -- nil (no error!)
print(tonumber(true)) -- nil
-- Base conversion
print(tonumber("ff", 16)) -- 255
print(tonumber("11", 2)) -- 3 (binary)
print(tonumber("77", 8)) -- 63 (octal)tostring(): jawna konwersja
tostring(v) konwertuje dowolną wartość na ciąg znaków. Dla liczb tworzy ciąg w zapisie dziesiętnym lub wykładniczym. Dla wartości logicznych tworzy "true" lub "false". Dla nil zwraca "nil". Dla tabel i funkcji zwraca adres, taki jak "table: 0x...", chyba że zdefiniowano metodę metatabeli __tostring.
print(tostring(42)) -- 42
print(tostring(3.14)) -- 3.14
print(tostring(true)) -- true
print(tostring(false)) -- false
print(tostring(nil)) -- nil
print(tostring({})) -- table: 0x...
-- Useful for safe concatenation
local val = nil
local msg = "Value: " .. tostring(val)
print(msg) -- Value: nilmath.tointeger()
math.tointeger(x) (Lua 5.3+) konwertuje liczbę zmiennoprzecinkową na całkowitą tylko wtedy, gdy wartość ma dokładny odpowiednik całkowity. Jeśli konwersja spowodowałaby utratę precyzji, zwraca nil. Jest to bezpieczniejsze niż math.floor(), które zawsze kończy się powodzeniem, ale może po cichu obciąć część ułamkową.
Należy używać tej funkcji, gdy wymagana jest ścisła walidacja liczby całkowitej, na przykład podczas korzystania z interfejsów API wymagających dokładnych liczb całkowitych.
print(math.tointeger(5.0)) -- 5 (exact)
print(math.tointeger(5.5)) -- nil (not exact)
print(math.tointeger(2^53)) -- 9007199254740992
-- Contrast with math.floor
print(math.floor(5.9)) -- 5 (truncates)
print(math.floor(5.0)) -- 5
-- Check before use
local n = math.tointeger(val) or error("need integer")Konwersja typów podczas porównań
Lua nie konwertuje typów podczas porównań równości. Wyrażenie 1 == "1" zawsze ma wartość false, ponieważ operandy mają różne typy. Operatory relacyjne (<, > itd.) powodują jednak konwersję między ciągami znaków a liczbami — ale tylko wtedy, gdy oba operandy są tego samego typu. Mieszanie typów w porównaniach porządkujących powoduje błąd.
print(1 == "1") -- false (no coercion)
print(1 == 1.0) -- true (int/float equal)
-- Ordering: same type only
print("abc" < "abd") -- true (string compare)
print(1 < 2) -- true (number compare)
-- This ERRORS: mixing string and number
-- print(1 < "2") -- attempt to compare number with stringPraktyka: analizowanie danych wejściowych użytkownika
Bardzo często stosowanym wzorcem w programach Lua jest odczytanie ciągu znaków z danych wejściowych użytkownika (np. za pomocą io.read()) i przekonwertowanie go na liczbę. Należy zawsze używać tonumber() i sprawdzać, czy wynik nie jest równy nil, aby poprawnie obsługiwać nieprawidłowe dane zamiast doprowadzać do awarii programu.
-- Safe input parsing pattern
local function parseNumber(input)
local n = tonumber(input)
if n == nil then
return nil, "Invalid number: " .. tostring(input)
end
return n, nil
end
local val, err = parseNumber("42")
print(val, err) -- 42 nil
local val2, err2 = parseNumber("abc")
print(val2, err2) -- nil Invalid number: abcPułapki precyzji liczb całkowitych i zmiennoprzecinkowych
Liczby zmiennoprzecinkowe mają ograniczoną precyzję. Operacje łączące liczby całkowite i zmiennoprzecinkowe mogą dawać nieoczekiwane wyniki ze względu na reprezentację IEEE 754. Największa liczba całkowita, którą można dokładnie reprezentować jako double, to 2^53 = 9,007,199,254,740,992. Liczby całkowite większe od tej wartości tracą precyzję po zapisaniu jako zmiennoprzecinkowe.
W Lua 5.3+ natywne 64-bitowe liczby całkowite obsługują dokładne wartości aż do 2^63-1, czyli znacznie większe. Gdy dokładność ma znaczenie, należy zawsze używać arytmetyki całkowitoliczbowej.
-- Float precision limit
print(2^53) -- 9.007...e+15
print(2^53 + 1 == 2^53) -- true (precision lost!)
-- Integer stays exact
local big = math.maxinteger
print(big) -- 9223372036854775807
print(math.type(big)) -- integer
-- Mixing promotes to float
print(math.type(1 + 1.0)) -- floatKonwersja formatu ciągu znaków
string.format() jest najbardziej rozbudowanym narzędziem do konwersji liczby na ciąg znaków, gdy potrzebna jest kontrola nad precyzją, dopełnianiem i zapisem. Funkcja korzysta ze specyfikatorów formatu printf języka C. Należy jej używać do wyświetlania danych, zapisu do plików oraz wszędzie tam, gdzie domyślna reprezentacja tostring() jest niewystarczająca.
print(string.format("%d", 255)) -- 255
print(string.format("%x", 255)) -- ff
print(string.format("%05d", 42)) -- 00042
print(string.format("%.2f", 3.14159)) -- 3.14
print(string.format("%e", 12345.0)) -- 1.234500e+04
print(string.format("%s=%d", "x", 10)) -- x=10Szybkie sprawdzenie
Co zwraca tonumber("hello") w Lua?
Podsumowanie: wymuszanie konwersji typów i konwersja
Czego się Państwo nauczyli:
- Lua automatycznie konwertuje ciągi znaków na liczby w działaniach arytmetycznych oraz liczby na ciągi znaków podczas konkatenacji
tonumber()zwraca nil w przypadku niepowodzenia — należy zawsze to sprawdzać!tostring()bezpiecznie konwertuje dowolną wartość na ciąg znaków- Równość (
==) nigdy nie powoduje konwersji — wartości różnych typów nigdy nie są równe - Do precyzyjnego formatowania liczb należy używać
string.format() - Limit precyzji liczb zmiennoprzecinkowych wynosi 2^53; dla dużych dokładnych wartości należy używać natywnych liczb całkowitych
Następnie: sterowanie przepływem za pomocą if/elseif/else i pętli.
Często zadawane pytania
Czy lekcja „Wymuszanie i konwersja typów” jest bezpłatna?
Tak — pełny tekst „Wymuszanie i konwersja typów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Lua Academy, przejdź na CoddyKit PRO. Kurs Lua Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Wymuszanie i konwersja typów”?
Proszę poznać automatyczne wymuszanie konwersji między ciągami znaków a liczbami oraz jawne użycie tonumber/tostring. Ćwiczysz Lua Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Lua Academy?
Nie wymagamy żadnego doświadczenia. Lua Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Wymuszanie i konwersja typów”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Lua Academy?
Tak. Każda lekcja Lua Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Przegląd typów danych Lua
- Deklarowanie zmiennych w Lua
- Operatory arytmetyczne i relacyjne
- Wymuszanie i konwersja typów