Op het briefje staat “3 eieren”. Daar bak je geen omelet mee.
Van briefje naar eieren is Parse. Eieren tellen en het getal opschrijven is ToString.
Parsing en .ToString()
Parsing briefje → eieren
zet een string om naar een ander type
int numVal =int.Parse("-105");
.ToString() eieren → briefje
de omgekeerde weg, naar tekst (dat elk type heeft)
int getal =5;string tekst = getal.ToString();
Tip
Niet zeker dat de gebruiker een geldig getal invoert? Dan is int.TryParse() je vriend (zie appendix).
Parse doet zijn best
Parse probeert de tekst te lezen. Lukt dat niet, dan crasht je programma.
Code
Resultaat
int.Parse(" 42 ")
42, spaties errond mogen
int.Parse("+7")
7
int.Parse("3 eieren")
crash: FormatException
int.Parse("4,5")
crash: geen geheel getal
int.Parse("3000000000")
crash: OverflowException, te groot voor een int
bool.Parse("ja")
crash: enkel true of false
Invoer van de gebruiker verwerken
ReadLine geeft altijd een string
De gebruiker typt 3 en daarna 4. Wat toont dit?
string a = Console.ReadLine();string b = Console.ReadLine();Console.WriteLine(a + b);
3 [enter] 4 [enter]
34
Zelfde invoer, ander resultaat.
Geen crash: de + plakt twee briefjes aan elkaar. ReadLine geeft je altijd een briefje, ook als de gebruiker een getal typt.
Waarschuwing
int getal = Console.ReadLine(); mag evenmin: de compiler weigert een string in een int te steken.
Van string naar getal
Uitlezen
met ReadLine
Bewaren
in een string
Parsen
naar het type dat je nodig hebt
De meest gebruikte zin dit semester
double gewicht =double.Parse(Console.ReadLine());
Wat de gebruiker typt komt binnen als string, Parse maakt er een double van.
.Parse
int getal =int.Parse(Console.ReadLine());
Enkel de Parse-methode verandert mee met het type dat je nodig hebt:
Gewenst type
Code
int
int.Parse(Console.ReadLine())
double
double.Parse(Console.ReadLine())
bool
bool.Parse(Console.ReadLine())
char
char.Parse(Console.ReadLine())
string
Console.ReadLine() (geen Parse nodig)
Opmerking
De komende hoofdstukken mag je ervan uitgaan dat de gebruiker foutloze invoer geeft.
Komma of punt?
In je code
schrijf je een kommagetal-literal altijd met een punt: 9.81 (onafhankelijk van je taalinstellingen)
Als invoer
hangt het van de landinstellingen af: een Belgisch systeem verwacht 9,81, een Engels 9.81
Een punt op een Belgische computer
Console.WriteLine("Geef het gewicht in kg:");double gewicht =double.Parse(Console.ReadLine());Console.WriteLine($"Dubbel zo zwaar: {gewicht * 2} kg");
Geef het gewicht in kg: 9.81 [enter]
Dubbel zo zwaar: 1962 kg
Waarschuwing
Het verkeerde scheidingsteken geeft geen foutmelding. Op een Belgische computer wordt 9.81 gelezen als 981, want de punt geldt daar als scheiding voor duizendtallen. Je programma rekent vrolijk verder met een gewicht van 981 kilogram.
Vreemde resultaten bij kommagetallen zonder dat er iets crasht? Kijk eerst welk teken je hebt getypt.
Hetzelfde recept, een ander land
Een Amerikaans recept schrijft 1.5, een Vlaams 1,5.
double.Parse leest het zoals je computer ingesteld is.
De Convert-bibliotheek
Naast casten en parsen is er nog een derde manier: Convert zet zowat elk type om naar elk ander type.
int g = Convert.ToInt32(2.7);// 3double d = Convert.ToDouble(5);// 5.0bool b = Convert.ToBoolean(1);// trueint l = Convert.ToInt32("19");// 19
Naar int is ToInt32, naar short is ToInt16.
Een keukenrobot: je ziet niet of er gecast of geparset wordt. En Convert.ToInt32rondt af, waar een cast afkapt.
Casting, conversie of parsing?
Alle omzettingen samengevat.
Casting en parsing zijn compact en werken ook in andere talen. Beheers ze dus, ook al is Convert verleidelijk eenvoudig.
Terug in de keuken
Casting kopje en kom2,7 eieren
Tussen getaltypes. (int)2.7 geeft 2: hij kapt af.
Parsing en ToString briefje
Tussen tekst en getal. int.Parse("3") geeft 3, 3.ToString() geeft "3".
Convert keukenrobot
Van alles naar alles, ook bool. Convert.ToInt32(2.7) geeft 3: hij rondt af.
Berekeningen met System.Math
Wat is een bibliotheek?
Een verzameling kant-en-klare methoden die iemand anders al geschreven heeft:
Console.WriteLine("Hallo");// bibliotheek Console, ken je aldouble w = Math.Sqrt(144);// bibliotheek Math, nieuw
Uitzonderingen zijn Abs, Max, Min en Clamp: die geven terug wat je erin stopt. Math.Abs(-42) is dus een int.
Methoden in elkaar schuiven
Het resultaat van een methode mag de parameter van een andere methode zijn. Dat deed je al in double.Parse(Console.ReadLine()). De afstand tussen speler en monster, met Pythagoras:
C# werkt van binnen naar buiten: eerst de twee machten, dan de optelling, en pas dat totaal gaat in Sqrt.
Waarden begrenzen
levens = Math.Max(levens - schade,0);// nooit onder 0oven = Math.Clamp(oven,50,250);// 300 wordt 250int verschil = Math.Abs(vandaag - gisteren);// 5, niet -5
Max / Min
de grootste of de kleinste van twee getallen
Clamp
begrenzen langs twee kanten tegelijk (waarde, ondergrens, bovengrens)
Abs
het minteken verdwijnt, ideaal voor “hoe groot is het verschil?”
Tip
Deze heb je in de praktijk vaker nodig dan alle sinussen samen.
Rekenen kan mislukken
Console.WriteLine(a / b);// int door 0: DivideByZeroExceptionConsole.WriteLine(x / y);// double door 0.0: oneindigConsole.WriteLine(Math.Sqrt(-1));// NaN, Not a Number
NaN is besmettelijk: NaN + 5 blijft NaN, NaN * 1000 ook.
Controleren doe je met double.IsNaN(resultaat), dat geeft je een bool.
Oneindig heeft ook een naam: double.PositiveInfinity en double.NegativeInfinity.
Belangrijk
Oneindig en NaN laten je programma niet crashen.
De foute berekening werkt stilletjes door, soms tot honderden regels verder waar je plots een onmogelijk resultaat ziet.
Het bereik in code
Elk datatype kent z’n eigen grenzen, en de compiler kent ze ook:
Console.WriteLine($"int gaat van {int.MinValue} tot {int.MaxValue}");
int gaat van -2147483648 tot 2147483647
En wat als je over die grens gaat?
int groot =int.MaxValue;Console.WriteLine(groot +1);// -2147483648
-2147483648
Waarschuwing
Overflow: de teller loopt over zoals de kilometerteller van een oude auto. Geen crash, geen waarschuwing. Verwacht je grote getallen, kies dan meteen een long.
Over afronden
Afkappen is niet afronden
Casting kapt af, ongeacht of er een 1 of een 9 na de komma staat.
Bij negatieve getallen zie je het verschil met echt afronden:
Console.WriteLine((int)-2.7);// -2, richting nulConsole.WriteLine(Math.Floor(-2.7));// -3, richting min oneindig
Math.Truncate doet exact wat een cast doet, maar geeft je een double terug.
Truncate, Floor en Ceiling
Floor en Ceiling gaan altijd dezelfde kant uit, een cast schuift altijd naar de nul toe.
Hoeveel bussen heb je nodig?
47 studenten, 20 per bus:
int aantalBussen =(int)Math.Ceiling(aantalStudenten /(double)perBus);// 3
47 / 20.0
2.35
Math.Ceiling
3.0
(int)
3
Overal waar je iets moet vullen (bussen, dozen, pagina’s) mag je niets laten liggen, en daar is Math.Ceiling voor.
Waarschuwing
Vergeet je de cast naar double, dan deel je twee gehele getallen en krijg je 2 nog voor Ceiling iets kan doen. Er staan dan 7 studenten op de parking.
Bankers rounding
Math.Round(4.5);// 4Math.Round(5.5);// 6
Ligt een getal exact op de helft, dan rondt Math.Round standaard af naar het dichtstbijzijnde even getal.
Waarschuwing
Handig voor bankiers, minder handig wanneer jouw quotering van 4.5 op 10 plots een 4 wordt.
Waarom naar het even getal?
Een bank rondt elke dag duizenden bedragen af en telt ze daarna op. Gaat elke helft naar boven, dan komt er telkens een halve eenheid bij, en die fouten stapelen zich op.
Naar het even getal gaat de ene helft naar boven en de andere naar beneden: de fouten heffen elkaar op.
Afronden zoals je verwacht
Geef een MidpointRounding mee. Treedt enkel in actie als het getal exact op de helft ligt:
Convert.ToInt32 doet ook aan bankers rounding, en daar kan je het niet afzetten. Rond dan eerst zelf af: (int)Math.Round(4.5, MidpointRounding.AwayFromZero).
De drie manieren naast elkaar
Waarde
(int)
Math.Round
met AwayFromZero
Convert.ToInt32
4.5
4
4
5
4
5.5
5
6
6
6
-2.5
-2
-2
-3
-2
Belangrijk
Kies bewust. Wil je afkappen, gebruik een cast of Math.Truncate. Wil je afronden, gebruik Math.Round met MidpointRounding.AwayFromZero. Doe je niets, dan krijg je bankers rounding.
behoudt de variabele al haar cijfers, enkel de tekst op het scherm is ingekort
Bij Math.Round
gooi je die cijfers echt weg
Tip
Rond pas af op het laatste moment, vlak voor je het resultaat toont. Rond je te vroeg af, dan sleep je die fout doorheen je hele berekening mee.
Wat de weegschaal toont
De weegschaal toont 250g. In de kom zit 250,37g.
F2 is het schermpje: de bloem blijft in de kom. Math.Round schept er echt iets uit.
Geld: reken niet met double
Console.WriteLine(0.1+0.2);// 0,30000000000000004double prijs =4.35;int centen =(int)(prijs *100);// 434 in plaats van 435!
4.35 * 100
levert 434.99999999999994
(int)
de cast kapt de rest af
434
in plaats van 435
Je klant is een cent kwijt, en bij duizend bestellingen merkt de boekhouding dat.
decimal prijs =4.35M;// decimal bewaart de cijfers decimaal
Tip
Voor alles wat op een kassaticket zou staan kies je decimal. Voor wetenschappelijke berekeningen, coördinaten en snelheden blijft double de juiste keuze.
Waarom decimal wel klopt
1/3 in het tiendelig stelsel
0,3333333... loopt eindeloos door. Ergens moet je stoppen.
0,1 binair (double)
0,000110011001100... loopt ook eindeloos door. De double kapt af en bewaart een getal net naast 0,1.
4.35M (decimal)
Bewaard als 435, met de komma twee plaatsen naar links. Tiendelig, net als jij: exact.
Zonder toeval lopen je monsters altijd dezelfde weg en krijg je altijd dezelfde wiskundeopgaven.
Maak eenmalig een generator en vraag dan getallen op:
Random generator =newRandom();int getal1 = generator.Next();int a = generator.Next(0,11);// 0 tot en met 10int b = generator.Next(55,100);// 55 tot en met 99
Belangrijk
De ondergrens telt mee, de bovengrens niet. Wil je een getal tot en met X, schrijf dan X + 1 als tweede parameter.
Tip
De new Random()-syntax pluizen we vanaf hoofdstuk 9 uit. Lig er nu nog niet van wakker.
Kommagetallen met NextDouble
NextDouble() geeft een getal tussen 0.0 en 1.0. Schaal en verschuif naar je bereik:
// tussen 5.0 en 12.5double r =5.0+(generator.NextDouble()*7.5);
Bereik = 12.5 - 5.0 = 7.5, daarna +5 om te verschuiven.
Een vaste seed
Een Random rekent zijn getallen uit, vertrekkend van een startgetal: de seed. Geef je zelf een seed mee tussen de haakjes, dan krijg je bij elke start dezelfde reeks:
Random generator =newRandom(666);Console.WriteLine(generator.Next(1,7));Console.WriteLine(generator.Next(1,7));Console.WriteLine(generator.Next(1,7));
1e keer starten:
4
2
2
2e keer starten:
4
2
2
Handig om je code te testen. Elk ander getal dan 666 is een andere seed.
Seeds in Balatro en Minecraft
Met dit ene getal
666
ligt je hele wereld vast. (het hoeft niet 666 te zijn, elk getal is een andere seed)
Zelfde seed, zelfde reeks
Jouw wereld op een andere pc
Er bestaan hele forums vol goeie seeds.
Debuggen
Logica vs syntax
Code die compileert, is enkel grammaticaal correct.
De betekenis kan nog altijd fout zijn:
Neem natriumNeem waterVoeg beide samen
Perfecte “code”, maar een logische fout (en een stevige explosie). Dat is een bug.
Een bug in Visual Studio?
“Meneer, ik heb een bug in Visual Studio gevonden.”
99%
van de keren zit die bug in je eigen code.
Proeven onderweg
Een kok proeft tussendoor, niet pas als het bord op tafel staat.
Een breakpoint doet dat met je programma.
Breakpoints
Klik links van een lijn voor een breakpoint (rode bol)
Je programma pauzeert daar
In Locals/Autos zie je de waarde van elke variabele
Je kan ook over een variabele hoveren.
Een breakpoint.
Door je code steppen
Continue
verder tot het volgende breakpoint of het einde
Step over (het gebogen pijltje)
één lijn verder, dan weer pauzeren
Stop (rode knop)
stoppen om je code aan te passen
Voorspel telkens eerst wat er moet gebeuren: welke waarden, welke output?
Klopt de werkelijkheid niet met je voorspelling, dan heb je waarschijnlijk een bug beet.
Waarschuwing
Zomaar door je code steppen en hopen dat de bug magisch verschijnt, werkt niet. Een programmeur die niet kan debuggen is als een vis die niet kan zwemmen.
Conclusie
Omzetten kan via casting, parsing en Convert: ken het verschil
keukenrobot
Narrowing (met dataverlies) vereist een cast, widening gaat vanzelf
kopje en kom2,7 eieren
ReadLine geeft altijd een string: parse naar het juiste type
briefje
Math rekent met kommagetallen en in radialen; oneindig en NaN crashen niet
oven
Kies bewust tussen afkappen en afronden; voor geld gebruik je decimal
weegschaal
Eén Random-generator volstaat; debuggen doe je door te voorspellen
proeven onderweg
Tip
Volgende halte: beslissingen nemen met if, vergelijkingen en switch.
Meer weten
Kennisclips
Alle kennisclips van H4: 19 korte clips over casten, invoer omzetten, Math, afronden, geld, Random en debuggen
round() doet in Python ook aan bankers rounding: ligt een getal op de helft, dan gaat het naar het dichtstbijzijnde even getal. Wat Python niet heeft is de MidpointRounding-parameter.