1. Reële getallen afronden
Zoals we al hebben besproken, wordt bij het toekennen van een reëel getal aan een int
variabele altijd naar beneden afgerond naar het dichtstbijzijnde kleinere gehele getal — het breukdeel wordt gewoon weggegooid.
Maar het is gemakkelijk om je een situatie voor te stellen waarin een gebroken getal moet worden afgerond naar het dichtstbijzijnde gehele getal in beide richtingen of zelfs naar boven moet worden afgerond. Wat doe je in dit geval?
Voor deze en voor veel vergelijkbare situaties heeft Java de Math
klasse, die de methoden round()
, ceil()
, en heeft floor()
.
Math.round()
methode
De Math.round()
methode rondt een getal af op het dichtstbijzijnde gehele getal:
long x = Math.round(real_number)
Maar er is nog een andere nuance: deze methode retourneert een long
geheel getal (geen int
). Omdat reële getallen erg groot kunnen zijn, besloten de makers van Java Java's grootste beschikbare gehele type te gebruiken: long
.
Dienovereenkomstig, als een programmeur het resultaat aan een variabele wil toewijzen int
, moet hij de compiler expliciet aangeven dat hij het mogelijke verlies van gegevens accepteert (in het geval dat het resulterende getal niet in een int
type past).
int x = (int) Math.round(real_number)
Voorbeelden:
Stelling | Resultaat |
---|---|
|
|
|
|
|
|
Math.ceil()
methode
De Math.ceil()
methode rondt een getal naar boven af op een geheel getal. Hier zijn voorbeelden:
Stelling | Resultaat |
---|---|
|
|
|
|
|
|
Math.floor()
methode
De Math.floor()
methode rondt een getal naar beneden af op een geheel getal. Hier zijn voorbeelden:
Stelling | Resultaat |
---|---|
|
|
|
|
|
|
Bij het afronden van een getal naar een geheel getal is het natuurlijk gemakkelijker om gewoon een type cast-operator te gebruiken:(int)
Stelling | Resultaat |
---|---|
|
|
Als je het moeilijk vindt om deze namen te onthouden, kan een korte Engelse les helpen:
Math
betekent wiskundeRound
betekent rondCeiling
betekent plafondFloor
betekent vloer
2. Hoe getallen met drijvende komma zijn gestructureerd
Het double
type kan waarden opslaan in het bereik van tot . Dit enorme bereik aan waarden (vergeleken met het type) wordt verklaard door het feit dat het type (evenals ) een geheel andere interne structuur heeft dan integer-typen. Intern codeert het type zijn waarde als twee getallen: de eerste wordt de mantisse genoemd en de tweede wordt de exponent genoemd .-1.7*10308
+1.7*10308
int
double
float
double
Laten we zeggen dat we het nummer hebben 123456789
en het opslaan als een double
variabele. Wanneer we dat doen, wordt het nummer geconverteerd naar , en intern slaat het type twee nummers op - en . De significand ("significant deel van het getal" of mantisse) is rood gemarkeerd, terwijl de exponent blauw is gemarkeerd.1.23456789*108
double
23456789
8
Deze aanpak maakt het mogelijk om zowel zeer grote als zeer kleine aantallen op te slaan. Maar omdat de weergave van het getal beperkt is tot 8 bytes (64 bits) en sommige bits worden gebruikt om de exponent op te slaan (evenals het teken van de mantisse en het teken van de exponent), zijn de maximale beschikbare cijfers om de mantisse weer te geven is 15 .
Dit is een zeer vereenvoudigde beschrijving van hoe reële getallen zijn gestructureerd.
3. Verlies van precisie bij het werken met reële getallen
Houd er bij het werken met reële getallen altijd rekening mee dat reële getallen niet exact zijn . Bij het omzetten van decimaal naar binair kunnen er altijd afrondings- en conversiefouten optreden . Bovendien is de meest voorkomende foutbron het verlies van precisie bij het optellen/aftrekken van getallen op radicaal verschillende schalen.
Dit laatste feit is een beetje verbluffend voor beginnende programmeurs.
Als we aftrekken van , krijgen we .1/109
109
109
Getallen aftrekken op radicaal verschillende schalen | Uitleg |
---|---|
|
Het tweede getal is extreem klein , waardoor de significantie (grijs gemarkeerd) wordt genegeerd. De 15 significante cijfers zijn oranje gemarkeerd. |
Wat kunnen we zeggen, programmeren is niet hetzelfde als wiskunde.
4. Valkuil bij het vergelijken van reële getallen
Een ander gevaar ligt op de loer voor programmeurs wanneer ze echte getallen vergelijken. Het ontstaat bij het werken met reële getallen, omdat afrondingsfouten zich kunnen ophopen. Het resultaat is dat er situaties zijn waarin wordt verwacht dat reële getallen gelijk zijn, maar dat is niet het geval. Of vice versa: de cijfers zijn naar verwachting verschillend, maar ze zijn gelijk.
Voorbeeld:
Stelling | Uitleg |
---|---|
|
De waarde van de variabele a zal zijn 1000000000.0 De waarde van de variabele c zal zijn 1000000000.0 (het getal in de b variabele is te klein) |
In bovenstaand voorbeeld zouden a
en c
niet gelijk moeten zijn, maar dat zijn ze wel.
Of laten we een ander voorbeeld nemen:
Stelling | Uitleg |
---|---|
|
De waarde van de variabele a zal zijn 1.0 De waarde van de variabele b zal zijn1.0 |
5. Een interessant feit overstrictfp
Java heeft een speciaal trefwoordstrictfp
( strict floating point ) , dat niet voorkomt in andere programmeertalen. En weet je waarom je het nodig hebt? Het verslechtert de nauwkeurigheid van bewerkingen met getallen met drijvende komma. Hier is het verhaal van hoe het tot stand kwam:
GO TO FULL VERSION