Developedia
Developedia
A szám típusok: int, float

A szám típusok: int, float

Két féle szám típust ismertünk meg:

  • int - egész számok (integer)
  • float - tizedes tört számok (floating point = lebegőpontos)

Szám típusú változók létrehozása

Azzal jelezzük, hogy egy szám float típusú, hogy a végére egy f betűt teszünk. (Úgynevezett: f suffix)

Alapműveletek számokon

Nézzük, meg milyen matematikai műveleteket tudunk rajtuk elvégezni!

Alap műveletek int-eken:

int a = 1, b = 2, c = -3;

int summa = 4 + a;       // összeadás
int difference = b - a;  // kivonás
int product = c * 2;     // szorzás
// Int osztás később...

Alapműveletek float-okon:

float a = 1.3f, b = -5.1f, c = 3f;

float summa = 4.9f + a;  // összeadás
float difference = b - a;// kivonás
float product = c * 2f;  // szorzás
float quotient = c / b;  // hányados

int-ek osztása esetén a kimenet lehet tört szám, ebben az esetben a tizedes rész levágásra kerül, csak az egész rész marad.

int a = 1, b = 2, c = -3;

int quotient1 = a / b; // 1.5 -> 1
int quotient2 = b - c; // -0.6˙ -> 0
int quotient2 = c / a; // -3

Mint látható változót és konstans számokat vegyítve használhatunk.

Operátorok

Az egyszerű műveleteket idegen szóval operáció-knak is nevezhetjük. (Gyakorlatban nem gyakran)

A műveletek elvégzésére használt karakter az operátor. (Ezt a fogalmat már szoktuk használni) Példák operátorokra: + - * /

Egy műveletnek lehetnek bemenetei és van egy kimente: A bemeneteket operandus-oknak nevezzük, a kimenetet visszatérés-nek.

image

Egy műveletre tekinthetünk úgy mint egy gép, ami vár megadott számú és típusú bemeneteket és ha megkapta őket, akkor legyárt valamilyen kimenetet:

image

Az, hogy a dobozon belül mi történik, például, hogy hogyan állítja elő a számítógép az összeget, az jelen pillanatban nem érdekel minket, csak a bemenetek, a kimenet és a köztük lévő logika.

Majd látni fogjuk, hogy nem minden esetben azonos a bemenetek és kimenetek típusa.

Ha egy műveletben az operandusok sorrendje nem számít, azt kommutatív műveletnek nevezzük. Ekkor az operandusok felcserélhetőek. Kommutatív művelet például az összeadás és a szorzás. (3+5) egyenlő (5+3)-mal. Nem kommutatív művelet példáául a kivonás vagy az osztás, hiszen (3-5) nem egyezik meg (5-3)-tel.

Alapműveletek Int és Float közt

Ha műveleteket végzünk egy int és egy float változón, a kimenet mindig float típusú.

int i = 10;
float f = 2.5f;

var summa = i + f ;     // float típusú.   Értéke: 12.5f
var difference = i - f; // float típusú.   Értéke: 7.5f
var product = i * f;    // float típusú.   Értéke: 25f
var quotient = i / f;   // float típusú.   Értéke: 4f

Dobozokkal kifejezve:

image

Matek vs. Programozás

Vegyük az következő programkódot példának:

Ha hasonló leírást látnánk egy matematikafüzetben joggal feltételeznénk, hogy a szerző a legalapvetőbb műveleteket sem érti. A leírtak szimplán hibásak lennének.

Ezzel szemben programozásban ez a kódrészlet teljességgel szabályos és értelmes.

int a, b, c;

a = 1;
b = 2;
c = a + b;
c = 7;

Matematikában:

Programozásban:

Igaz állítások egy sorozatát adjuk meg.

Végrehajtandó műveletek egy sorozatát adjuk meg.

Ha megnézzük a példa utolsó sorát, ott nem kijelentjük, hogy c értéke 7, hanem c-nek a 7-es értéket adjuk bármi is volt előtte.

int a = 1, b = 2, c;
c = a + b;
Console.WriteLine(c);  // Kiírja: 3
c = 7;
Console.WriteLine(c);  // Kiírja: 7

// Unityben így írnánk ki:    Debug.Log(c);

A negálás művelet

Nem minden operátornak van 2 bemenete. Egy számot tudunk negálni ebben az esetben csak egy bemeneti érték van.

int i = 6;
float f = -77.7f;

var iNeg = -i; // Típus: int     Érték: -6
var fNeg = -f; // Típus: float   Érték: 77.7f

A modulo művelet

A jól ismert összeadáson, kivonáson, szorzáson, osztáson és negáláson kívül még létezik egy alapművelet, amire szintén minden programozási nyelvben egy operátorral elvégezhető.

Ez a modulo művelet és a % operátort használjuk rá C#-ban. Ehhez két megjegyzés:

  1. Ez a művelet a magyar matematikai szakirodalomban kongruencia néven szerepel, én azonban a modulo kifejezést fogom továbbra is használni, mert az informatikában az az elterjedtebb.
  2. (A C# nyelv készítői által választott operátor a modulo műveletre a százalék karakter: %. Ennek ellenére semmi köze nincs a modulonak a százalék matematikai fogalmához. Egyszerűen csak ez a karakter volt szabad.

Úgy a legegyszerűbb a modulo műveletet megérteni, hogy visszagondolunk arra az időszakra, mikor általános iskolában az osztást tanultuk, de a törtek fogalmával még nem voltunk tisztában.

Ekkor ha osztanunk kellet, így végeztük el:

14 osztva 4-gyal egyenlő 3-mal, maradék a 2

23 osztva 5-tel egyenlő 4-gyel, maradék a 3

Ez a bizonyos maradék lesz a modulo művelet eredménye.

// 14 osztva 4-gyal egyenlő 3-mal, maradék a 2
int q1 = 14 / 4;   // Eredmény: 3
int m1 = 14 % 4;   // Eredmény: 2

// 23 osztva 5-tel egyenlő 5-tel, maradék a 3
int q2 = 23 / 5;   // Eredmény: 4
int m2 = 23 % 5;   // Eredmény: 3

Habár a float számoknál a számítógép nem csapja le a tizedes pont/vessző utáni részt, a modulo művelet ugyanúgy értelmezett flaot-okon is.

float q2 = 63.5f / 10f;   // Eredmény: 6.35f
float m2 = 63.5f % 10f;   // Eredmény: 3.5f

Kifejezések

Kifejezésnek nevezünk bármit, aminek az eredménye egy meghatározott típusú adat.

Egy változónak például egy ilyen kifejezést tudunk értékül adni.

Például egy kifejezés lehet egy konstans érték: int a = 2; int b = 3; int c = 42;, egy másik változó: int i = a; int j = i; , vagy bármiféle összetett művelet eredménye: int y = -2 * 23 - 5; int y = i + 3 * 4 - a / 2;.

Ha valaminek egy konkrét típusa és értéke van az mind kifejezés.

Zárójelek, műveleti sorrend

A matematikai jelöléstanban létezik a már jól megszokott műveleti sorrend. Egy bizonyos művelet lehet azonos, magasabb- vagy alacsonyabb rendű, mint egy másik művelet. Például:

A szorzás magasabb rendű művelet, mint az összeadás.

Az összeadás és a kivonás azonos rendű művelet.

Mit is jelent ez?

Ha zárójelek nélkül írunk le egy kifejezést, akkor mindig a magasabb rendűt hajtjuk először végre.

Azonos rendű műveletek esetén pedig azt, ami az olvasásban előrébb (ballra) van.

Ez a C#-ban is ugyanígy működik:

float f1 = 2.5f + 2 / 8 * 10 - 4;

// Ez lépésről lépésre lebontva így hajtódna végre:
float f2 = 2 / 8;      // 0.25
float f3 = f2 * 10;    // 2.5
float f4 = 12 + f3;    // 5
float f5 = f4 - 4;     // 1

// Azaz zárójelezve:
float f6 = (2.5f + ((2 / 8) * 10)) - 4;     // 1

Ahogy azt megszokhattuk a matematikában, a C#-ban is használhatunk zárójeleket a műveleti sorrend módosítására.

// Ha a fenti kifejezést igy írnánk le, akkor az teljesen más eredményt adna:
float g1 = 2.5f + ((2 / 8) * (10 - 4));    // 4

// Ez lépésről lépésre lebontva így hajtódna végre:
float g2 = 2 / 8;      // 0.25
float g3 = 10 - 4;     // 6
float g4 = g2 * g3;    // 1.5
float g5 = 2.5f + g4;  // 4

Olvashatóság kedvéért gyakran azonban célszerű a többszörösen összetett kifejezéseket több sorra bontani.

Egyszerűsítések

C#-ban létezik néhány egyszerűsített kifejezési forma gyakori feladatokra.

Ha egy változónak olyan értéket adunk, ami egy művelet eredménye, amiben a változó előző értékét használjuk első paraméterként, akkor annak leírása a következő módon egyszerűsíthető.

Ha pontosan 1-gyel akarunk növelni vagy csökkenteni egy szám típusú változó értékén, még egyszerűbb dolgunk van:

A kasztolás

Egy változó nem változtathatja meg típusát menet közben. (A C# statikusan típusos nyelv)

Egy értéket viszont sok esetben át tudunk alakítani egyik típusból egy másikba. Ezt kasztolástnak vagy casting-nak nevezzük.

Ez az átalakítás lehetséges például az int és a float típusok közt is.

Nézzük meg a következő példakódot:

float f = 2.5;
int i = 3;

float f2 = i;       // Implicit kasztolás    f2 érték:   3f
int i2 = (int) f;   // Explicit kasztolás    i2 érték:   2

Látható, hogy két különböző módja is van a kasztolásnak:

  • Implicit kasztolás: Az átalakítás automatikusan végbemegy.
  • Pl.: int → float

  • Explicit kasztolás: Külön jeleznünk kell, hogy végre akarom hajtani az átalakítást.
  • A ( ) operátorral végezzük és a zárójelen belül ki kell írni milyen típusba alakítunk:

    Pl.: flaot → int

    A float-ból int-be történő kasztolás úgy történik, hogy elhagyjuk a törtrészt.

Figyeljük meg, hogy az int-ből float-tá alakításnál nem történik adatvesztés (fogjuk rá), míg float-ból int-be történő átalakításnál igen, hiszen a tizedespont utáni részt lecsapjuk.

Ezért van az, hogy float-ból int-be alakításnál jeleznünk kell, hogy szándékosan végezzük a műveletet: Explicit nyilatkoznunk kell róla, hogy tudjuk, mit csinálunk.

Ez azért van így, hogy nehezebben kövessünk el hibát és lőjük magunkat lábon vele.

// Ezért is lehetséges, hogy egy int értéket adunk egy flaot változónak.
// A háttérben egy láthatatlan implicit cast-olás történik.
float f = 5;

// Ez így viszont hibás:
int i = 4.5f; // 🛑 Fordítási idejű error-t kapunk

Int, Long, Float, Double

Korábban megismerkedtünk az int és a float típusokkal. Ám a C#-ban egyéb primitív azaz beépített szám típusok is vannak ezek általában vagy az int-hez hasonlóan egész számot vagy a float-hoz hasonlóan tört számot tartalmaznak. Mért van akkor mégis szükség rájuk? A legnagyobb különbség az, hogy hány bit-et használnak fel egy szám ábrázolására.

Minél több bites egy egész szám típusú adat, annál magasabb számokat tud tartalmazni a pozitív tartományban, a negatív tartományban pedig annál alacsonyabbakat.

Ez így van a lebegőpontos számokra is, de emellett a több bites lebegőpontos törtek még nagyobb pontossággal is tudják tárolni számokat, mint a kevesebb bites verzióik.

Emellett még lehet egy szám előjeles vagy előjel nélküli is. Az előjel nélküli számok nem vehetnek fel negatív értéket, csak pozitívat.

Egész (Előjeles)
Egész (Előjel nélküli)
Lebegőpontos (Bináris)
Lebegőpontos (Decimális)
1 byte (8 bit)
sbyte
byte
-
-
2 byte(16 bit)
short
ushort
-
-
4 byte (32 bit)
int
uint
float
-
8 byte (64 bit)
long
ulong
double
-
16 byte (128 bit)
-
-
-
decimal

Jelenleg nem kell nagyon foglalkoznunk egyéb szám típusokkal az int-en és a float-on kívül, de érdemes fejben tartani a létezésüket.

(A binárisan és decimálisan tárolt lebegőpontos számok közti különbségekkel most nem nagyon foglalkozunk. Egyelőre legyen elég annyi, hogy a decimális formában történő tárolás valamivel pazarlóbb a memóriával, de bizonyos feladatokra alkalmasabb.)

A későbbiekben lesz pár matematikai függvény, amik csak double-okon működnek.

Bővebb információk a különböző szám típusokról: Adatmennyiség: Bitek és bájtokAdatmennyiség: Bitek és bájtok

Logo

Főoldal

Blog

Elmélet

3D Studio

Adatvédelmi nyilatkozat

GY.I.K.

Házirend

Szerző: Marosi Csaba / marosi.csaba@3d-studio.hu

DiscordGitHubLinkedIn
int i = 1;      // Int típusú változó deklarálása és definiálása
float f = 3.5f; // Float típusú változó deklarálása és definiálása
                // Programozásban mindig tizedes pontot használunk (nem vesszőt)

var i2 = 5;     // Ez így int típusú  változó lesz
var f2 = 5f;    // Ez így float típusú  változó lesz
var d1 = 5.0;   // Ez így se nem float, de nem int, hanem double típusú,
							  // amivel itt nem foglalkozunk.

float f3 = 5;   // Ha kiírjuk a típust, akkor egészből is lehet float.

float f4 = 4.0; // Ez így HIBÁS!   float változó <- Double érték
int i3 = 4f;    // Ez így HIBÁS!   int változó <- Float érték
float f = 3;

// A következő 2 művelet teljesen ekvivalens:
f = f + 6;   // f értékéhez hozzáadunk 6-ot
f += 6;      // f értékéhez hozzáadunk 6-ot

// A következő 2 művelet teljesen ekvivalens:
f = f - 3;   // f értékéből kivonunk 3-at
f -= 3;      // f értékéből kivonunk 3-at

// A következő 2 művelet teljesen ekvivalens:  
f = f * 8;   // f értékét szorozzuk 8-cal
f *= 8;      // f értékét szorozzuk 8-cal

// A következő 2 művelet teljesen ekvivalens:
f = f / -2;  // f értékét osztjuk 2-vel
f /= -2;     // f értékét osztjuk 2-vel
int i = 5;

// A következő 4 művelet teljesen ekvivalens:
i = i + 1;   // i értékét növeljük 1-gyel
i += 1;      // i értékét növeljük 1-gyel
i++;         // i értékét növeljük 1-gyel
++i;         // i értékét növeljük 1-gyel
		
// A következő 4 művelet teljesen ekvivalens:
i = i - 1;   // i értékét csökkentjük 1-gyel
i -= 1;      // i értékét csökkentjük 1-gyel
i--;         // i értékét csökkentjük 1-gyel
--i;         // i értékét csökkentjük 1-gyel