Zwevendekommagetallen

Op deze pagina, ga je leren hoe computers niet-hele getallen opslaan.

De manier waarop computers getallen op slaan die niet heel zijn heet zwevendekommagetal.

Waar komt die rare naam vandaan?
Deze rare naam wordt gebruikt omdat er vroeger een vastkommagetal-notatie was voor niet-hele getallen met een vast aantal getallen achter de komma. Bijvoorbeeld een vastekommagetalnotatie met 2 getallen achter de komma werd gebruikt om een hoevelheid geld in euro's en centen te laten zien. Omdat geldbedragen altijd maar 2 getallen achter de komma hebben. Maar tegenwoordig gebruiken computers altijd zwevendekommagetallen om niet-hele getallen te laten zien, zelfs voor geld.
Zwevendekommagetallen laten computers hele grote getallen opslaan, inclusief decimalen, maar het gebruikt nog steeds een specifiek aantal bits en dat zorgt ervoor dat er een limiet zit op de reeks waardes die een zwevendekommagetal aan kan namen, net als met hele getallen. Maar waardes die buiten de reeks vallen bij zwevendekommagetallen, kunnen resulteren in afrondfouten.
  1. Probeer bijvoorbeeld Geen Afbeelding een keer met bignums aan en een keer zonder.

De decimale vertegenwoordiging van ⅓ is 0.33333... Het bevat oneindig veel cijfers dus het dichtstbij dat je kan komen met een zwevendekommagetal is niet precies ⅓. Op een bepaald moment houdt het op omdat je computer niet genoeg geheugen heeft.

Afrondfouten kunnen zorgen voor onintuïtieve resultaten...

  1. Probeer Geen Afbeelding en dan Geen Afbeelding.

Dit is geen bug in Snap!, Snap! rapporteert netjes het resultaat dat berekent wordt volgens de hardware voor een zwevendekommagetal.

Hoe kan een simpele berekening zulke foute resultaten geven?
Deze resultaten lijken verrassend omdat een breuk zoals 2/10, exact kan worden opgeschreven in decimalen, als 0.2 namelijk (in tegenstelling tot ⅓). Maar met binaire getallen kunnen alleen breuken waarbij de noemer (het onderste getal) 2 is, exact worden weergegeven. Dus 2/16 kan wel, maar 2/10 niet. Het afgeronde getal waarmee in binair 0.2 wordt weergegeven is net ietsje groter dan 0.2, Dit geldt ook voor het afgeronde getal van 0.4, samen zijn deze 2 afrondfouten zo groot dat de optelsom van 0.2 en 0.4 niet meer klopt.

Hoe goed de hardware ook is, bepaalde soorten berekeningen geven waarschijnlijk grove fouten met zwevendekommagetallen. Een simpel voorbeeld is twee getallen van elkaar aftrekken die heel dicht bij elkaar liggen. Het correcte antwoord ligt in dat geval in de buurt van nul en als de getallen dicht genoeg bij elkaar liggen zal door afrondfouten het resultaat van de berekening onderstromen. Dit betekent dat het gerapporteerde resultaat lager ligt dan het daadwerkelijke resultaat. Dus bij de aftreksom 2 - 2.0001 wordt dan 0 gerapporteerd in plaats van 0.0001.

Fouten door zwevendekommmagetallen kunnen heel duur zijn en zelfs zorgen voor slachtoffers.

Een beroemd voorbeeld is de Ariane-raket die gelanceerd werd op 4 Juni 1996. Tijdens de 37ste seconde van de vlucht, probeerde het systeem een 64-bit zwevendekommagetal om te zetten in een 16-bitgetal, maar in plaats daarvan werd er een overstroomfout gerapporteerd, wat werd geïnterpreteerd door het navigatiesysteem als vliegdata. Dit zorgde ervoor dat de raket van zijn koers ging en zichzelf verwoestte.

Het Patriot-raketafweersysteem dat gebruikt werd tijdens de Golfoorlog had ook last van een afrondfout (Skeel 1992, U.S. GAO 1992). Het systeem gebruikte een tijdmeter die werkte met hele getallen en optelde met intervallen van 0.1 secondes. Het probleem was dat de hele getallen werden omgezet in decimale getallen door zich te vermenigvuldigen met de binaire benadering van 0.1: 0.00011001100110011001100 2 = 209715/2097152.

Dit betekende dat na 100 uur (3.6 × 10 6 tellen), er een fout was van

(\frac{1}{10}-\frac{209715}{2097152})(3600\times100\times10)=\frac{5625}{16384} \approx 0.3433 \text{ seconds}

Dit verschil zorgde ervoor dat het systeem niet meer goed zijn doel kon vinden. Toen dus later een Irakese raket werd afgevuurd die niet werd gestopt door het systeem, kwamen er 28 mensen om het leven.

Overgenomen van Analoge en Digitale Conversie (Engels) , door Wikibooks bijdragers, https://en.wikibooks.org/wiki/Analog_and_Digital_Conversion/Fixed_Wordlength_Effects

Computerberekeningen met hele getallen zijn simpel: of je krijgt een correct, heel getal of als het resultaat niet past in (niet-bignum) een heel getal dan krijg je een overstroomfout en wordt het resultaat, als het goed is, omgezet in een zwevendekommagetal (zoals bij 30!).

Computerberekeningen met zwevendekommagetallen daarentegen zijn moeilijk om precies goed te krijgen. Voor 1985 had ieder computermodel een ander formaat zwevendekommagetal en allemaal gaven ze foute antwoorden op bepaalde vragen. Deze situatie werd opgelost door de IEEE 754 zwevendekommastandaard die nu door iedere computerfabrikant gebruikt wordt.

Er zijn alternatieven voor zwevende komma's.
Als de kleine fouten die veroorzaakt worden door zwevendekommagetallen onacceptabel blijken te zijn in bepaalde gevallen, dan kan een programma ervoor kiezen alternatie notaties te gebruiken:
  • Exacte Rationale getallen. Twee bignums, één voor de noemer en één voor de teller, kunnen gebruikt worden om een breuk precies te noteren.
  • Binair gecodeerde decimalen. Een decimaal getal kan genoteerd worden met vier bits, de niet gebruikte bit-combinaties kunnen gebruikt worden voor voor een minteken en een komma. Een reeks van deze decimale cijfers kan gebruikt worden om een decimaal getal weer te geven. Je kan zo ook een breuk in decimalen weergeven dat precies een breuk noteert met een eindig aantal van deze binair-gecodeerde decimalen. Dus stel dat we de code 1110 voor . gebruiken, dan is 1.32 gelijk aan 0001 1110 0011 0010. Dit voorkomt het 0.2+0.4-probleem, maar werkt niet voor breuken die in decimaal een oneindige reeks cijfers nodig hebben zoals ⅓.
  • Decimale zwevendekommagetallen. Als de notatie met binair gecodeerde decimalen van hierboven wordt uitgebreid met een bit-combinatie die zegt "keer tien tot de macht" kunnen decimale getallen met de wetenschappelijke notatie genoteerd kunnen worden. Dus stel dat de code voor "keer tien tot de macht" gelijk is aan 1111, dan is 2.5e+4 gelijk aan: 0010 1110 0101 1111 0100. (We hebben gezien in de vorige les dat e+ gelijk is aan "keer tien tot de macht")

Zonder bignums wordt een resultaat dat te groot is voor een heel getal, omgezet in een zwevendekommagetal.
Geen Afbeelding

  1. Probeer 200! zonder bignums.
    Geen Afbeelding

Wat gebeurt er? Ook al is 200! vrij groot het is niet "oneindig". Het foute resultaat wordt veroorzaakt door de limiet van de grootte van zwevendekommagetallen. Als het resultaat van de berekening groter is dan kan worden opgeslagen dan rapporteert de computer een speciale code die de taal interpreteert als Oneindig of ∞.

Voor zwevendekommagetallen zijn er speciale codes voor oneindig, -oneindig (kleiner dan elke andere waarde) en "Niet een Getal" (afgekort als NaN in het Engels) dat gebruikt wordt als resultaat voor een illegale berekening zoals 0/0.
Geen Afbeelding
  1. Stel je een decimaal zwevendekommagetal voor met één significant getal en een exponent van 10 -2 tot 10 2 . Het kleinste positieve getal dat we kunnen weergeven met deze notatie is 0.01 (1×10 -2 ) en het grootste getal is 900 (9×10 2 ). Schets een getallenlijn van 0 tot 1000 en markeer al de positieve waardes die we kunnen weergeven met deze notatie. Wat kan je zeggen over de afstand tussen de waarde? Hoeveel breuken kunnen weergegeven worden? Hoeveel hele getallen onder de 1000 kunnen niet weergegeven worden? Wat zijn de voor- en nadelen van deze notatie? (Echte zwevendekommagetallen hebben veel meer waardes die weergegeven kunnen worden, maar de afstand op de getallenlijn is vergelijkbaar met die van deze notatie.)

Hoe weet een programmeertaal of het een bitreeks moet interpreteren als een heel getal, een zwevendekommagetal, een stuk tekst of iets anders? Programmeertalen doen dit op verschillende manieren, maar er is altijd een aantal extra bits die aangeven wat het data-type is van een bitreeks, die dus vertelt aan de computer hoe de bitreeks geïnterpreteerd moet worden.

Op het laagste niveau van abstractie wordt alles in een computer weergegeven als een binaire reeks. Bijvoorbeeld:
Maar verschillende talen gebruiken data-types op andere manieren.

In goed ontworpen talen (zoals talen gebaseerd op Scheme) zit het data-type vast aan de waarde zelf, dit zijn talen met dynamische waardes. In andere talen is het zo dat wanneer je een variabele aanmaakt, je moet zeggen wat voor type waarde de variabele zal bevatten. Dan zit het data-type dus vast aan de variabele, talen met dit systeem zijn talen met statische waardes. Stel je wilt een variabele x de waarde 5 geven, in een taal met dynamische waardes zou dat er zo uit kunnen zien:
x = 5;
In een taal met statische waardes ziet dat er zo uit:
Getal x;x wordt aangemaakt als een Getal-variabele.
x = 5; x krijgt de waarde 5.

Snap! heeft pluspunten die veel andere talen niet hebben en het is zeer waarschijnlijk dat je bij je volgende informaticacursus een taal met statische waardes zal leren gebruiken.

  1. Een bepaald programma gebruikt 4 bits om hele getallen weer te geven. Wanneer dat programma 9 en 7 optelt is het resultaat 0. Vind de beste verklaring voor dit resultaat.
    Er is iets fout gegaan met de data tijdens de som door een technische fout
    Dit resultaat werd veroorzaakt door een afrondfout.
    Dit resultaat werd veroorzaakt door een overstroomfout.
    Een zwevendekommagetal werd gebruikt om een benadering te geven van het resultaat.
Terug Volgende