Operatory arytmetyczne i przypisania
Cztery działania, reszta z dzielenia i kilka skrótów, bez których nie obejdzie się żaden program. Poznasz też pułapkę, na którą nabiera się niemal każdy początkujący: dlaczego 7 / 2 daje w C# trzy, a nie trzy i pół.
Czego się dziś nauczysz
- Wykonasz cztery działania arytmetyczne na zmiennych
- Wyjaśnisz, czym różni się dzielenie całkowite od zmiennoprzecinkowego
- Użyjesz operatora
%do sprawdzania podzielności i rozbijania liczb - Odróżnisz
i++od++ii wskażesz, kiedy to ma znaczenie - Zapiszesz działanie skrótem
+=zamiast pełną formą - Ustalisz kolejność wykonywania działań w złożonym wyrażeniu
Cztery działania i reszta
Operator to symbol wykonujący działanie. Wartości, na których działa, nazywamy operandami.
int wynik = 15 + 4;
// ^^ ^ ^
// | | └── drugi operand
// | └── operator
// └── pierwszy operand
| Operator | Nazwa | Przykład | Wynik |
|---|---|---|---|
+ | dodawanie | 15 + 4 | 19 |
- | odejmowanie | 15 - 4 | 11 |
* | mnożenie | 15 * 4 | 60 |
/ | dzielenie | 15 / 4 | 3 — uwaga! |
% | reszta z dzielenia (modulo) | 15 % 4 | 3 |
int a = 15;
int b = 4;
Console.WriteLine($"{a} + {b} = {a + b}"); // 19
Console.WriteLine($"{a} - {b} = {a - b}"); // 11
Console.WriteLine($"{a} * {b} = {a * b}"); // 60
Console.WriteLine($"{a} / {b} = {a / b}"); // 3
Console.WriteLine($"{a} % {b} = {a % b}"); // 3
Zwróć uwagę na dwie ostatnie linie: 15 / 4 daje 3, a nie 3,75. To nie błąd — to zamierzone zachowanie, które omawiamy w następnej sekcji.
Operatory jednoargumentowe
int liczba = 5;
int dodatnia = +liczba; // 5 — plus jednoargumentowy, praktycznie nieużywany
int ujemna = -liczba; // -5 — zmienia znak na przeciwny
Console.WriteLine($"{dodatnia} {ujemna}"); // 5 -5
Dzielenie całkowite i reszta
Najważniejsza zasada tej lekcji
Gdy oba operandy są liczbami całkowitymi, wynik dzielenia też jest liczbą całkowitą. Część ułamkowa jest odrzucana, a nie zaokrąglana.
Console.WriteLine(7 / 2); // 3 — nie 3,5 i nie 4
Console.WriteLine(9 / 2); // 4 — nie 4,5
Console.WriteLine(1 / 2); // 0 — nie 0,5!
Console.WriteLine(-7 / 2); // -3 — ucięcie w stronę zera
Żeby dostać wynik z częścią ułamkową, wystarczy, żeby choć jedna strona była typu double:
int suma = 7;
int ile = 2;
Console.WriteLine(suma / ile); // 3 ✗ oba całkowite
Console.WriteLine(7.0 / 2); // 3,5 ✓ literał z kropką
Console.WriteLine((double)suma / ile); // 3,5 ✓ rzutowanie zmiennej
Console.WriteLine(suma / (double)ile); // 3,5 ✓ obojętne, którą stronę
Rzutowanie musi być przed dzieleniem, nie po
double x = (double)(suma / ile); nie pomoże. Nawias każe najpierw wykonać dzielenie całkowite — wynik 3 — i dopiero tę trójkę zamienić na 3,0. Reszta przepadła, zanim zdążyliśmy cokolwiek rzutować.
Operator % — reszta z dzielenia
Modulo zwraca to, co zostaje po podzieleniu. Wygląda niepozornie, a jest jednym z najczęściej używanych operatorów w praktyce.
Console.WriteLine(17 % 5); // 2 bo 17 = 3*5 + 2
Console.WriteLine(20 % 5); // 0 dzieli się bez reszty
Console.WriteLine(3 % 5); // 3 mniejsza od dzielnika, więc cała jest resztą
Do czego naprawdę służy modulo
| Zadanie | Zapis | Jak to działa |
|---|---|---|
| Czy liczba jest parzysta? | liczba % 2 == 0 | Parzyste dzielą się przez 2 bez reszty. |
| Czy podzielna przez 3? | liczba % 3 == 0 | Ta sama zasada dla dowolnego dzielnika. |
| Ostatnia cyfra liczby | liczba % 10 | Reszta z dzielenia przez 10 to zawsze cyfra jedności. |
| Cyfra dziesiątek | liczba / 10 % 10 | Najpierw obcinamy jedności, potem bierzemy nową ostatnią cyfrę. |
| Zawijanie w zakresie | (indeks + 1) % dlugosc | Po ostatnim elemencie wraca do zera — przydatne przy karuzelach i kolejkach. |
| Godziny z minut | minuty / 60 i minuty % 60 | Dzielenie daje pełne godziny, reszta — minuty. |
int liczba = 4738;
int jednosci = liczba % 10; // 8
int dziesiatki = liczba / 10 % 10; // 3
int setki = liczba / 100 % 10; // 7
int tysiace = liczba / 1000 % 10; // 4
Console.WriteLine($"{tysiace} {setki} {dziesiatki} {jednosci}"); // 4 7 3 8
Dzielenie przez zero
| Sytuacja | Co się dzieje |
|---|---|
liczby całkowite, np. a / b gdy b to 0 | Program przerywa działanie z błędem DivideByZeroException. |
liczby zmiennoprzecinkowe, np. 1.0 / 0.0 | Program działa dalej, a wynikiem jest ∞ (nieskończoność). |
0.0 / 0.0 | Wynikiem jest NaN — „nie-liczba”. |
Skąd ta różnica
Typy zmiennoprzecinkowe mają w standardzie zarezerwowane wartości specjalne na nieskończoność i „nie-liczbę”. Typy całkowite ich nie mają, więc nie da się w nich zapisać żadnego sensownego wyniku — stąd błąd.
W praktyce oznacza to, że przed dzieleniem przez zmienną warto sprawdzić, czy nie jest zerem. Jak to zrobić, poznasz w lekcji o instrukcjach warunkowych.
Zwiększanie i zmniejszanie o jeden
Dodanie jedynki do zmiennej zdarza się tak często, że język ma na to osobny skrót.
int licznik = 5;
licznik = licznik + 1; // sposób pełny
licznik += 1; // sposób skrócony
licznik++; // sposób najkrótszy — wszystkie trzy robią to samo
Analogicznie licznik-- odejmuje jeden.
i++ czy ++i?
Oba zwiększają zmienną o jeden. Różnią się tym, co zwracają, gdy użyjesz ich w większym wyrażeniu.
i++ — najpierw użyj
Zwraca starą wartość, a dopiero potem zwiększa zmienną.
++i — najpierw zwiększ
Najpierw zwiększa zmienną, a potem zwraca nową wartość.
int a = 5;
int wynikA = a++; // wynikA dostaje 5, dopiero potem a staje się 6
Console.WriteLine($"a = {a}, wynikA = {wynikA}"); // a = 6, wynikA = 5
int b = 5;
int wynikB = ++b; // b staje się 6, wynikB dostaje 6
Console.WriteLine($"b = {b}, wynikB = {wynikB}"); // b = 6, wynikB = 6
a = 6, wynikA = 5
b = 6, wynikB = 6
W praktyce ta różnica prawie nigdy nie ma znaczenia
Jeśli piszesz licznik++; jako osobną instrukcję — a tak jest w 99% przypadków — obie wersje zachowują się identycznie, bo nikt nie korzysta ze zwróconej wartości.
Różnica pojawia się dopiero wtedy, gdy wciśniesz ++ w środek większego wyrażenia. Nie rób tego. Zapis tablica[i++] = i++ * 2; jest legalny, ale nieczytelny i niemal zawsze oznacza błąd w projekcie kodu. Rozbij taki kod na osobne linie.
Przypisania złożone
Wzorzec „weź zmienną, coś z nią zrób, wynik włóż z powrotem” jest tak częsty, że dla każdego działania istnieje skrót.
| Skrót | Znaczy dokładnie to samo co | Przykład |
|---|---|---|
x += 5 | x = x + 5 | dopisanie do sumy |
x -= 5 | x = x - 5 | odjęcie od stanu konta |
x *= 2 | x = x * 2 | podwojenie |
x /= 4 | x = x / 4 | podzielenie |
x %= 3 | x = x % 3 | zostawienie samej reszty |
int liczba = 10;
liczba += 5; // 15
liczba -= 3; // 12
liczba *= 2; // 24
liczba /= 4; // 6
liczba %= 4; // 2
Console.WriteLine(liczba); // 2
// Działa też dla tekstu
string zdanie = "Ala";
zdanie += " ma kota";
Console.WriteLine(zdanie); // Ala ma kota
Drobna różnica, o której warto wiedzieć
Skróty złożone wykonują rzutowanie automatycznie. Zapis bajt += 1; zadziała, a rozpisany bajt = bajt + 1; — nie, bo dodawanie daje wynik typu int, którego nie da się bez pytania wcisnąć z powrotem do byte. Wracaliśmy do tego w lekcji 06.
Kolejność wykonywania działań
C# stosuje te same reguły co matematyka: najpierw nawiasy, potem mnożenie i dzielenie, na końcu dodawanie i odejmowanie.
| Kolejność | Operatory | Uwaga |
|---|---|---|
| 1 — pierwsze | ( ) | nawiasy wyprzedzają wszystko |
| 2 | ++ -- - (jednoargumentowy) | działają na jednej wartości |
| 3 | * / % | modulo ma taki sam priorytet jak mnożenie |
| 4 | + - | — |
| 5 — ostatnie | = += -= … | przypisanie wykonuje się na samym końcu |
Console.WriteLine(2 + 3 * 4); // 14 bo 3*4 policzy się pierwsze
Console.WriteLine((2 + 3) * 4); // 20 nawias zmienia kolejność
Console.WriteLine(10 - 4 - 3); // 3 od lewej: (10-4)-3
Console.WriteLine(20 / 4 * 2); // 10 od lewej: (20/4)*2, nie 20/(4*2)
Console.WriteLine(10 + 6 % 4); // 12 bo 6%4 wykonuje się przed dodawaniem
Nawias nic nie kosztuje
Nie musisz uczyć się całej tabeli na pamięć. Gdy masz wątpliwość, postaw nawiasy — program będzie działał tak samo szybko, a kod stanie się jednoznaczny dla każdego, kto go przeczyta.
double srednia = (a + b + c) / 3.0; czyta się lepiej niż wersja bez nawiasów, nawet gdyby dawała ten sam wynik.
Operator + dla tekstu
Ten sam znak plus, użyty na napisach, skleja je ze sobą. Nazywamy to konkatenacją.
string imie = "Anna";
string nazwisko = "Kowalska";
string pelne = imie + " " + nazwisko;
Console.WriteLine(pelne); // Anna Kowalska
// Można sklejać tekst z liczbą — liczba sama zamieni się na tekst
int wiek = 17;
Console.WriteLine("Wiek: " + wiek); // Wiek: 17
Klasyczna pułapka: kiedy plus dodaje, a kiedy skleja
Decyduje typ operandów i kolejność od lewej do prawej:
Console.WriteLine("Suma: " + 2 + 3); // Suma: 23 ✗ nie 5!
Console.WriteLine("Suma: " + (2 + 3)); // Suma: 5 ✓ nawias ratuje
Console.WriteLine(2 + 3 + " to suma"); // 5 to suma ✓ tu liczby są pierwsze
W pierwszej linii C# najpierw skleja "Suma: " z liczbą 2, dostaje tekst "Suma: 2", a potem dokleja do niego 3. W trzeciej linii kolejność jest odwrotna: najpierw dodaje 2 i 3, bo obie są liczbami, i dopiero wynik skleja z tekstem.
Interpolacja rozwiązuje ten problem raz na zawsze
Zamiast żonglować nawiasami, używaj zapisu ze znakiem $. Wewnątrz klamer wyrażenie liczy się normalnie, a dopiero wynik trafia do tekstu:
Console.WriteLine($"Suma: {2 + 3}"); → Suma: 5
Dlatego w tym kursie prawie zawsze używamy interpolacji, a sklejania plusem tylko wtedy, gdy naprawdę łączymy dwa napisy.
Klasa Math — gotowe działania
Pierwiastek, potęga i zaokrąglanie nie mają własnych operatorów. Zamiast nich używa się metod z klasy Math. Jest ona statyczna, więc nie tworzy się jej obiektu — wywołujemy metody przez nazwę klasy.
| Metoda | Zwraca | Co robi |
|---|---|---|
Math.Abs(x) | ten sam typ | Wartość bezwzględna — usuwa znak minus. Math.Abs(-7) → 7. |
Math.Pow(x, y) | double | Podnosi x do potęgi y. Math.Pow(2, 10) → 1024. |
Math.Sqrt(x) | double | Pierwiastek kwadratowy. Math.Sqrt(25) → 5. Dla liczby ujemnej zwraca NaN. |
Math.Round(x, n) | double | Zaokrągla do n miejsc po przecinku. Bez drugiego argumentu — do liczby całkowitej. |
Math.Floor(x) | double | Zaokrągla w dół: Math.Floor(4.9) → 4. |
Math.Ceiling(x) | double | Zaokrągla w górę: Math.Ceiling(4.1) → 5. |
Math.Max(a, b) | ten sam typ | Większa z dwóch liczb. |
Math.Min(a, b) | ten sam typ | Mniejsza z dwóch liczb. |
Math.PI | double | Stała π ≈ 3,14159265358979. To pole, nie metoda — bez nawiasów. |
double promien = 3.0;
double pole = Math.PI * promien * promien;
double obwod = 2 * Math.PI * promien;
Console.WriteLine($"Pole: {Math.Round(pole, 2)}"); // 28,27
Console.WriteLine($"Obwod: {Math.Round(obwod, 2)}"); // 18,85
Console.WriteLine(Math.Pow(2, 10)); // 1024
Console.WriteLine(Math.Sqrt(144)); // 12
Console.WriteLine(Math.Abs(-15)); // 15
Console.WriteLine(Math.Max(7, 12)); // 12
Uwaga na Math.Pow przy liczbach całkowitych
Math.Pow zawsze zwraca double, nawet dla Math.Pow(5, 3). Rzutowanie wyniku na int bywa zawodne, bo obliczenia zmiennoprzecinkowe mogą dać 124,99999999999999 zamiast równych 125 — a rzutowanie ucina część ułamkową, dając 124.
Gdy potęgujesz liczby całkowite i zależy ci na dokładnym wyniku, bezpieczniej użyć (int)Math.Round(Math.Pow(5, 3)) albo po prostu pomnożyć liczbę przez siebie.
Kasa samoobsługowa — wydawanie reszty
Klient płaci banknotem za zakupy. Program ma policzyć resztę i rozmienić ją na jak najmniejszą liczbę nominałów. To klasyczne zastosowanie pary / i %.
// Wszystko liczymy w groszach, żeby uniknąć ułamków
int doZaplatyGrosze = 4737; // 47,37 zl
int wplataGrosze = 10000; // 100,00 zl
int resztaGrosze = wplataGrosze - doZaplatyGrosze;
Console.WriteLine($"Do zaplaty: {doZaplatyGrosze / 100},{doZaplatyGrosze % 100:D2} zl");
Console.WriteLine($"Wplata: {wplataGrosze / 100},{wplataGrosze % 100:D2} zl");
Console.WriteLine($"Reszta: {resztaGrosze / 100},{resztaGrosze % 100:D2} zl");
Console.WriteLine();
// Rozmieniamy resztę na nominały — od największego do najmniejszego
int pozostalo = resztaGrosze;
int banknoty50 = pozostalo / 5000; pozostalo %= 5000;
int banknoty20 = pozostalo / 2000; pozostalo %= 2000;
int banknoty10 = pozostalo / 1000; pozostalo %= 1000;
int monety5 = pozostalo / 500; pozostalo %= 500;
int monety2 = pozostalo / 200; pozostalo %= 200;
int monety1 = pozostalo / 100; pozostalo %= 100;
int grosze = pozostalo;
Console.WriteLine("Wydac:");
Console.WriteLine($" 50 zl x {banknoty50}");
Console.WriteLine($" 20 zl x {banknoty20}");
Console.WriteLine($" 10 zl x {banknoty10}");
Console.WriteLine($" 5 zl x {monety5}");
Console.WriteLine($" 2 zl x {monety2}");
Console.WriteLine($" 1 zl x {monety1}");
Console.WriteLine($" gr x {grosze}");
Do zaplaty: 47,37 zl
Wplata: 100,00 zl
Reszta: 52,63 zl
Wydac:
50 zl x 1
20 zl x 0
10 zl x 0
5 zl x 0
2 zl x 1
1 zl x 0
gr x 63
Omówienie
| Fragment | Dlaczego tak |
|---|---|
| Liczenie w groszach | Zamiast 47.37 trzymamy 4737. Dzięki temu wszystkie działania są na liczbach całkowitych i nie ma mowy o zgubionym groszu. To standardowa sztuczka w systemach kasowych i bankowych. |
resztaGrosze / 100 |
Dzielenie całkowite daje pełne złotówki — tu właśnie chcemy ucięcia części ułamkowej. |
resztaGrosze % 100 |
Reszta z dzielenia przez 100 to grosze. Razem z poprzednim daje pełną kwotę. |
:D2 |
Format wymuszający dwie cyfry z zerem wiodącym. Bez niego 3 grosze wypisałyby się jako 52,3 zamiast 52,03. |
pozostalo %= 5000; |
Po odliczeniu banknotów pięćdziesięciozłotowych zostawiamy tylko resztę. Kolejny nominał pracuje już na tym, co zostało. |
| Kolejność nominałów | Idziemy od największego do najmniejszego. Odwrotna kolejność dałaby poprawną kwotę, ale wydaną w samych groszach. |
Na co uważać
| Kod | Problem |
|---|---|
double s = suma / ile; |
Oba operandy całkowite — reszta przepada przed przypisaniem. Trzeba rzutować jeden z nich: (double)suma / ile. |
double s = (double)(suma / ile); |
Rzutowanie po nawiasie, czyli za późno. Dzielenie już się wykonało całkowicie. |
"Suma: " + 2 + 3 |
Da Suma: 23. Potrzebny nawias albo, lepiej, interpolacja. |
x = x++; |
Wygląda niewinnie, a nie zmienia wartości x. Przypisanie nadpisuje wynik zwiększenia starą wartością. Wystarczy x++;. |
int i = 10 / 0; |
Dzielenie przez stałe zero to błąd kompilacji CS0020, a nie wyjątek. Przy zmiennej byłby wyjątek w czasie działania. |
int p = Math.Pow(2, 3); |
CS0266 — Math.Pow zwraca double. Potrzebne rzutowanie. |
Math.PI() |
PI to pole, nie metoda. Bez nawiasów. |
int x = 5; x =+ 3; |
Odwrócone znaki. To nie jest +=, tylko przypisanie liczby +3 — x będzie miało 3, a nie 8. Kompilator nie zgłosi błędu. |
Zadania
Zapisz na kartce wynik każdej linii, a dopiero potem uruchom program.
Console.WriteLine(10 / 3);
Console.WriteLine(10 % 3);
Console.WriteLine(10.0 / 3);
Console.WriteLine(2 + 3 * 4 - 1);
Console.WriteLine((2 + 3) * (4 - 1));
Console.WriteLine("Wynik: " + 5 + 5);
Console.WriteLine(100 % 10 % 3);
pokaż rozwiązanie
3
1
3,3333333333333335
13
15
Wynik: 55
0
Linia 3 — 10.0 ma kropkę, więc jest typu double i całe dzielenie liczy się dokładnie. Ogon cyfr to znany nam już efekt zapisu dwójkowego.
Linia 4 — mnożenie przed dodawaniem: 2 + 12 − 1 = 13.
Linia 6 — tekst plus 5 daje "Wynik: 5", a potem dokleja się drugą piątkę.
Linia 7 — od lewej: 100 % 10 to 0, a 0 % 3 to nadal 0.
Mając liczbę sekund (np. 9876), wypisz ją w formacie godz:min:sek z zerami wiodącymi. Użyj wyłącznie operatorów / i %.
pokaż rozwiązanie
int sekundyRazem = 9876;
int godziny = sekundyRazem / 3600;
int minuty = sekundyRazem % 3600 / 60;
int sekundy = sekundyRazem % 60;
Console.WriteLine($"{godziny:D2}:{minuty:D2}:{sekundy:D2}");
02:44:36
Godzina ma 3600 sekund, więc dzielenie całkowite daje pełne godziny: 9876 / 3600 = 2.
Dla minut najpierw usuwamy pełne godziny (% 3600 zostawia 2676), a potem dzielimy przez 60 — wychodzi 44.
Sekundy to po prostu reszta z dzielenia przez 60. Nie trzeba wcześniej nic odejmować, bo % 60 i tak pomija wszystkie pełne minuty.
Format D2 dopisuje zero wiodące, dzięki czemu widzimy 02 zamiast 2.
Dla liczby czterocyfrowej (np. 4738) oblicz sumę jej cyfr oraz iloczyn. Nie używaj pętli ani konwersji na tekst — same operatory.
pokaż rozwiązanie
int liczba = 4738;
int c1 = liczba / 1000; // 4 tysiace
int c2 = liczba / 100 % 10; // 7 setki
int c3 = liczba / 10 % 10; // 3 dziesiatki
int c4 = liczba % 10; // 8 jednosci
int suma = c1 + c2 + c3 + c4;
int iloczyn = c1 * c2 * c3 * c4;
Console.WriteLine($"Cyfry: {c1} {c2} {c3} {c4}");
Console.WriteLine($"Suma: {suma}");
Console.WriteLine($"Iloczyn: {iloczyn}");
Cyfry: 4 7 3 8
Suma: 22
Iloczyn: 672
Schemat jest zawsze ten sam: dzielenie odcina cyfry z prawej, modulo wybiera ostatnią z tego, co zostało. Przy pierwszej cyfrze % 10 jest zbędne, bo po dzieleniu przez 1000 została już tylko jedna cyfra.
Po lekcji o pętlach wrócisz do tego zadania i napiszesz wersję działającą dla liczby o dowolnej długości.
Dla prostokąta o bokach 7,5 i 3,2 oblicz pole, obwód i długość przekątnej. Wyniki zaokrąglij do dwóch miejsc po przecinku.
pokaż rozwiązanie
double a = 7.5;
double b = 3.2;
double pole = a * b;
double obwod = 2 * (a + b);
double przekatna = Math.Sqrt(a * a + b * b);
Console.WriteLine($"Pole: {pole:F2}");
Console.WriteLine($"Obwod: {obwod:F2}");
Console.WriteLine($"Przekatna: {przekatna:F2}");
Pole: 24,00
Obwod: 21,40
Przekatna: 8,15
Przekątną liczymy z twierdzenia Pitagorasa. Zapis a * a jest tu lepszy niż Math.Pow(a, 2) — krótszy, szybszy i bez ryzyka niedokładności.
Zwróć uwagę na nawias w obwodzie. Bez niego 2 * a + b policzyłoby coś zupełnie innego.
Program ma policzyć średnią z trzech ocen i pole koła. Nie działa poprawnie — znajdź i popraw cztery usterki. Uwaga: nie wszystkie z nich zatrzymają kompilację.
int ocena1 = 5, ocena2 = 4, ocena3 = 4;
double srednia = ocena1 + ocena2 + ocena3 / 3;
Console.WriteLine("Srednia: " + srednia);
double promien = 2.5;
int poleKola = Math.PI * promien * promien;
Console.WriteLine("Pole: " + poleKola);
pokaż rozwiązanie
int ocena1 = 5, ocena2 = 4, ocena3 = 4;
double srednia = (ocena1 + ocena2 + ocena3) / 3.0; // 1. nawias 2. dzielenie przez 3.0
Console.WriteLine($"Srednia: {srednia:F2}");
double promien = 2.5;
double poleKola = Math.PI * promien * promien; // 3. double, nie int
Console.WriteLine($"Pole: {poleKola:F2}"); // 4. interpolacja + zaokrąglenie
Srednia: 4,33
Pole: 19,63
Błąd 1 — brak nawiasu. Dzielenie ma wyższy priorytet niż dodawanie, więc oryginalny kod liczył 5 + 4 + (4 / 3), czyli 5 + 4 + 1 = 10. Program się kompilował i wypisywał bzdurę — to najgroźniejszy rodzaj błędu.
Błąd 2 — dzielenie całkowite. Nawet z nawiasem 13 / 3 dałoby 4 zamiast 4,33. Trzeba dzielić przez 3.0.
Błąd 3 — zły typ. Math.PI to double, więc całe wyrażenie jest typu double i nie zmieści się w int. To jedyny błąd, który zatrzyma kompilację (CS0266).
Błąd 4 — brak zaokrąglenia. Bez formatu F2 zobaczylibyśmy 19,634954084936208. Przy okazji zamieniamy sklejanie plusem na interpolację.
W lekcji 04 zamieniałeś wartości dwóch zmiennych, używając trzeciej pomocniczej. Zrób to teraz bez niej, korzystając wyłącznie z dodawania i odejmowania.
pokaż rozwiązanie
int a = 5;
int b = 9;
Console.WriteLine($"Przed: a = {a}, b = {b}");
a = a + b; // a = 14 (mamy w a sume obu liczb)
b = a - b; // b = 14 - 9 = 5 (czyli stare a)
a = a - b; // a = 14 - 5 = 9 (czyli stare b)
Console.WriteLine($"Po: a = {a}, b = {b}");
Przed: a = 5, b = 9
Po: a = 9, b = 5
Sztuczka polega na tym, że po pierwszej linii zmienna a przechowuje sumę obu liczb. Odejmując od niej jedną, dostajemy drugą.
Ale nie używaj tego w prawdziwym kodzie. Wersja z trzecią zmienną jest czytelniejsza, a ta może się przepełnić, gdy suma przekroczy zakres typu. To ciekawostka pokazująca, że ten sam efekt da się osiągnąć różnymi drogami — nie zalecana praktyka.
Co trzeba zapamiętać
- Dzielenie dwóch liczb całkowitych daje liczbę całkowitą — reszta jest odrzucana, nie zaokrąglana.
- Żeby dostać ułamek, rzutuj jedną stronę na
double— przed dzieleniem, nie po. %zwraca resztę. Służy do sprawdzania podzielności, wyciągania cyfr i zawijania indeksów.- Dzielenie całkowite przez zero przerywa program; zmiennoprzecinkowe daje nieskończoność.
i++zwraca starą wartość,++inową. Jako osobna instrukcja są nierozróżnialne — i tak należy ich używać.x += 5to skrót odx = x + 5. Działa też dla tekstu.- Kolejność jak w matematyce: nawiasy, potem
* / %, na końcu+ -. W razie wątpliwości postaw nawias. - Plus przy tekście skleja.
"Suma: " + 2 + 3daSuma: 23— używaj interpolacji. - Pierwiastek, potęga i zaokrąglanie to metody klasy
Math.Math.PIjest polem, więc bez nawiasów.