Waarom het ingewikkeld is
JavaScript’s Math object biedt een methode voor het afronden op hele getallen. Als we willen afronden naar een vast aantal decimalen, dan moeten we dat zelf doen. Dit artikel gaat niet in op de details van floating-point rekenen, maar in het kort komt het erop neer dat de meeste programmeertalen een binaire floating-point representatie gebruiken die alleen veel decimale breuken kan benaderen. Dit resulteert in afrondingsfouten voor de meest voorkomende benaderingen van afronding in JavaScript.
Afrondingsfouten
De meest voorkomende oplossingen voor afronding op een decimaal is om ofwel Number.prototype.toFixed()
te gebruiken, of de float met een macht van 10 te vermenigvuldigen om Math.round()
te gebruiken. Beide werken, behalve dat soms een decimaal van 5 naar beneden wordt afgerond in plaats van naar boven.
Number((1.005).toFixed(2)); // 1 instead of 1.01
Math.round(1.005*100)/100; // 1 instead of 1.01
Een betere oplossing
Het afrondingsprobleem kan worden vermeden door getallen te gebruiken die in exponentiële notatie worden weergegeven:
Number(Math.round(1.005+'e2')+'e-2'); // 1.01
En om dat te abstraheren tot iets bruikbaarders:
function round(value, decimals) { return Number(Math.round(value+'e'+decimals)+'e-'+decimals);}round(1.005, 2); // 1.01