Vezérlőpult
B3. Lebegőpontos típusok és a decimal · Változók és típusok

B blokk · Változók és típusok · 3. tananyag

Lebegőpontos típusok és a decimal

Az átlag, az ár, a testmagasság nem egész — kell egy típuscsalád a törteknek is. Csakhogy a törtvilág trükkös: a saját szemeddel látod majd, hogy a gép szerint 0.1 + 0.2 nem pontosan 0.3 — és megtanulod a szakma vasszabályát: pénzt soha ne számolj double-ben.

2 tanóraA 0.1 + 0.2 rejtélyPénzhez: decimal

Tanulási célok

1Egészekkel nem megy — a törtvilág

Számoljunk átlagot a B2 eszközeivel:

int jegy1 = 4;
int jegy2 = 5;
Console.WriteLine((jegy1 + jegy2) / 2);   // 4  — pedig 4.5 kellene!

Egész / egész = egész — a 4,5-ből 4 lett. Ide új típus kell: olyan, amely törtrészt is tárol. A C# hármat is ad, és a választás közöttük nem ízlés kérdése.

2A három törttípus

TípusMéretPontosság (értékes jegy)LiterálMire való?.NET-név
float4 bájt~7 jegy3.14f3D-grafika, ahol a hely számít — nálunk ritkaSystem.Single
double8 bájt~15–16 jegy3.14az alapértelmezés: mérés, tudomány, játékSystem.Double
decimal16 bájt28–29 jegy3.14mpénz és minden pontos tizedesSystem.Decimal

Három dolog, amit rögzíts:

  1. A tizedes literál alapból double — a 3.14 önmagában double.
  2. Utótag jelöli a másik kettőt: 3.14f → float, 3.14m → decimal (a 3.14d → double, de ezt nem szokás kiírni). Utótag nélkül a float f = 3.14; le sem fordul (CS0664) — a fordító nem hajlandó csendben pontosságot veszíteni.
  3. A float és a double neve onnan jön, hogy a tizedespont „lebeg”: a gép a számot egy szorzat alakjában tárolja (számjegyek × 2 valamelyik hatványa), így ugyanaz a típus tud nagyon nagy és nagyon kicsi számot is — de mindig csak korlátos számú értékes jeggyel.
double magassag = 1.72;
float sebesseg = 12.5f;
decimal ar = 2499.90m;
⚠️ EMLÉKEZTETŐ (B1)

A tizedes elválasztó a kódban mindig pont. A 3,14 a fordítónak két külön dolog: egy 3-as meg egy 14-es.

3A nagy meglepetés: 0.1 + 0.2

Írasd ki — a saját gépeden, most:

Console.WriteLine(0.1 + 0.2);     // 0.30000000000000004

Nem elírás, és nem a géped romlott el. A magyarázat: a gép kettes számrendszerben tárol, és ott a 0.1 végtelen szakaszos tört — pontosan úgy, ahogy tízes számrendszerben az 1/3 = 0,33333… sosem írható le véges számjeggyel. A double a 0.1-nek csak egy nagyon jó közelítését tudja eltárolni, és a parányi kerekítési hibák összeadódva néha láthatóvá válnak.

Ez nem bug — ez a lebegőpontos ábrázolás természete, minden nyelvben így van (a JavaScript is ezt csinálja). A kérdés csak az, mikor számít:

4A decimal — a pénz típusa

A decimal tízes számrendszerben tárol — pontosan úgy „gondolkodik”, ahogy a papíron számolunk. A 0.1m tényleg pontosan 0.1:

double d = 0.1 + 0.2;
decimal m = 0.1m + 0.2m;

Console.WriteLine(d);     // 0.30000000000000004
Console.WriteLine(m);     // 0.3   — pontosan

Egy valósághű árszámítás — csupa decimal:

decimal nettoAr = 1999.00m;
const decimal AfaSzorzo = 1.27m;      // B1: a bűvös szám konstansba való!

decimal bruttoAr = nettoAr * AfaSzorzo;
Console.WriteLine(bruttoAr);          // 2538.7300

Az ára: a decimal lassabb és kisebb a tartománya (kb. ±7,9 × 10²⁸ — azért ez is bőven elég egy államadósságra). Cserébe 28–29 értékes jegy, tizedesen pontosan.

A döntési szabály

Kell törtrész? nem int darabszám (B2) igen Pénz, vagy tizedesen pontos kell? nem double mérés, tudomány, játék igen decimal ár, egyenleg, számla
Két kérdés, és megvan a típus: darabszám → int · mérés → double · pénz → decimal.

A Mastermindban int-ek lesznek; a kalandjáték boltjában (II. félév) decimal árak.

5Aritmetika és zárójelezés

A műveleti sorrend (precedencia)

A C# ugyanúgy számol, ahogy a matekórán tanultad:

  1. zárójel — mindent felülír;
  2. *, /, % — szorzás, osztás, maradék;
  3. +, - — összeadás, kivonás;
  4. azonos szinten balról jobbra.
Console.WriteLine(2 + 3 * 4);     // 14  — előbb a szorzás
Console.WriteLine((2 + 3) * 4);   // 20  — a zárójel felülír
Console.WriteLine(10 - 4 - 3);    // 3   — balról jobbra: (10-4)-3

A klasszikus átlag-csapda:

int jegy1 = 4;
int jegy2 = 5;

Console.WriteLine(jegy1 + jegy2 / 2);     // 6  — ROSSZ: csak a jegy2 feleződött!
Console.WriteLine((jegy1 + jegy2) / 2);   // 4  — jobb, de még egészosztás…
💡 TIPP

Ha egy pillanatig is gondolkodnod kell a sorrenden, zárójelezz. A fölösleges zárójel nem hiba — az olvashatóság eszköze (A9: a kódot többször olvassák, mint írják).

Amikor egész és tört keveredik

És most a B2-es szálka feloldása. Ha egy műveletben az egyik oldal tört, az egész fél automatikusan törtté lép elő, és az eredmény is tört:

Console.WriteLine(7 / 2);       // 3    — int / int = int
Console.WriteLine(7 / 2.0);     // 3.5  — int / double = double!
Console.WriteLine(7.0 / 2);     // 3.5  — ez is

Így már megvan a helyes átlag is:

Console.WriteLine((jegy1 + jegy2) / 2.0);   // 4.5  ✔
ℹ️ ELŐREUTALÁS

Ez az automatikus „előlépés” egy implicit konverzió — a konverziók teljes rendszerét a B6-ban tesszük rendbe. Most a mintát jegyezd meg: egy jól elhelyezett .0 a kifejezésben átbillenti az osztást a törtvilágba.

int, double vagy decimal?

Melyik típust választanád az adatnak? A döntési ábra segít!

1 / 8Pontszám: 0
…

6Gyakori hibák

TünetMi történt?Mit tegyél?
CS0664: Literal of type double cannot be implicitly converted…float f = 3.14; vagy decimal d = 3.14; — hiányzik az utótag3.14f, illetve 3.14m
0.30000000000000004 a kimenetena double bináris kerekítése — nem bugpénznél/pontos tizedesnél válts decimal-ra; másutt hagyd
Az átlag egész lett (4, nem 4.5)minden operandus egész volt → egészosztástegyél a kifejezésbe 2.0-t, vagy használj tört típusú változót
jegy1 + jegy2 / 2 fura eredményt ada / előbb hajtódik végre, mint a +zárójelezd: (jegy1 + jegy2) / 2.0
A 3,14 beírása hibasort dobvessző a pont helyetta tizedes elválasztó a kódban mindig pont

7Gyakorlat — a meglepetéstől a blokkig

  1. Új projekt: Console App, név: Tortek, .NET 10.
  2. Reprodukáld a meglepetést: írasd ki a 0.1 + 0.2-t double-ként, majd 0.1m + 0.2m-ként. Tegyél töréspontot, és a Locals-ban is nézd meg a két értéket!
  3. Bevásárlás-számoló — csupa decimal:
decimal kenyer = 899.50m;
decimal tej = 429.90m;
decimal sajt = 1249.00m;

decimal osszesen = kenyer + tej + sajt;
Console.WriteLine(osszesen);              // 2578.40
  1. Bővítsd: az árak bruttók; számold ki a blokk ÁFA-tartalmát (27%-os kulccsal: osszesen - osszesen / 1.27m) — és a 1.27m-et tedd konstansba (B1!).
  2. Átlag helyesen: két int jegyből számolj double átlagot a 2.0-trükkel.
  3. Commitold (Tort tipusok es aritmetika gyakorlat).
✅ ELLENŐRZŐ PONT

Láttad a 0.30000000000000004-et és mellette a decimal pontos 0.3-ját; a blokk végösszege 2578.40; az átlagod 4.5.

8Feladatok

Gyakorló feladatok

⭐ alap · ⭐⭐ haladó · ⭐⭐⭐ kihívás

B3.1⭐

Melyik sor fordul le, melyik nem — és miért? double a = 2.5; · float b = 2.5; · float c = 2.5f; · decimal d = 2.5; · decimal e = 2.5m;

B3.2⭐

Számold ki papíron, aztán ellenőrizd géppel: 2 + 3 * 4 · (2 + 3) * 4 · 10 - 4 - 3 · 10 - (4 - 3) · 2 + 10 / 2 · (2 + 10) / 2

B3.3⭐⭐

Egy munkatársad ezt írta három jegy átlagára: jegy1 + jegy2 + jegy3 / 3.0 — a teszteléskor furcsa értékek jönnek ki. Mi a hiba, és hogyan javítanád? Próbáld ki a 4, 5, 3 jegyekkel!

B3.4⭐⭐

Írj „kasszablokkot”: három tétel bruttó ára decimal-ban, végösszeg, majd az ÁFA-tartalom kiírása. A 27%-os kulcs konstans legyen. Ellenőrizd az összegeket számológéppel!

B3.5⭐⭐⭐

Adj össze tízszer 0.1-et egy double változóban (a B2-es rövidítéssel: osszeg += 0.1; tíz sorban), és írasd ki. Mit kapsz 1.0 helyett? Ismételd meg decimal-lal. Magyarázd el 3-4 mondatban, mi történt — és hogy miért pont a decimal „tudja jól”.

9Önellenőrző kvíz

Ellenőrizd magad!

Minden kérdésnél egy válasz helyes. A végén pontszámot kapsz.

10Fogalomtár

FogalomJelentés
lebegőpontos (floating point)törtszám-ábrázolás, amelyben a tizedespont „lebeg”: számjegyek × 2 hatványa
float / double4 / 8 bájtos lebegőpontos típus, ~7 / ~15–16 értékes jeggyel
decimal16 bájtos, tízes alapú törttípus, 28–29 értékes jeggyel — a pénz típusa
literál-utótaga literál típusát jelöli: f (float), m (decimal), d (double, elhagyható)
értékes jegyahány számjegyet a típus megbízhatóan tárol — a pontosság mértéke
kerekítési hibaa bináris közelítésből eredő parányi eltérés (0.1 + 0.2 ≠ 0.3)
precedencia (műveleti sorrend)zárójel → * / % → + -, azonos szinten balról jobbra
implicit konverzió (előzetes)az egész automatikus „előlépése” törtté vegyes kifejezésben — részletek: B6

11Összegzés

  1. Három törttípus: float (ritka), double (az alapértelmezés, ~15–16 jegy), decimal (tízes alapú, pénzhez). Utótagok: f, m.
  2. A 0.1 + 0.2 = 0.30000000000000004 nem bug: a 0.1 binárisan végtelen szakaszos, a double közelítve tárolja — mint tízesben az 1/3-ot.
  3. Vasszabály: darabszám → int, mérés → double, pénz → decimal — számlán egy fillér eltérés sem megengedett.
  4. A műveleti sorrend a matekos: zárójel → * / % → + -, balról jobbra. Ha gondolkodnod kell rajta, zárójelezz.
  5. Vegyes kifejezésben az egész törtté lép elő: 7 / 2.0 = 3.5 — egy jól elhelyezett .0 átbillenti az osztást a törtvilágba (a teljes konverziórendszer: B6).