BDS Software

Javascript Rounding

I don't find the Math.round function in Javascript to be acceptable. When the decimal fraction of a number is exactly 0.5, Math.round always rounds up to the next highest integer. But, this is NOT in accordance with the accepted IEEE 754 standard.

Wikipedia - Nearest Integer Function says:

In computer science, the nearest integer function of real number x denoted variously by [ x ] ... or Round(x), is a function which returns the nearest integer to x. To avoid ambiguity when operating on half-integers, a rounding rule must be chosen. On most computer implementations, the selected rule is to round half-integers to the nearest even integer -- for example,

[ 1.25 ] = 1

[ 1.50 ] = 2

[ 1.75 ] = 2

[ 2.25 ] = 2

[ 2.50 ] = 2

[ 2.75 ] = 3

[ 3.25 ] = 3

[ 3.50 ] = 4

[ 3.75 ] = 4

[ 4.50 ] = 4

etc.

This is in accordance with the IEEE 754 standard and helps reduce bias in the result.


Therefore, I have written a function to more closely approximate the IEEE 754 standard's methodology. Since Javascript stores all numbers as 64-bit doubles (whether they're intended to be integers, floats, doubles, unsigned ints, or whatever), there is an inherent lack of precision in the sixteenth decimal place. Thus, my function ignores the sixteenth decimal place, and centers a 0.499999999999999 value on 0.500000000000000. The code for this mdjRound() function is:

function mdjRound(input)
{

var sgn, trunc, frac, frac15, frac15t, output;

// Get the sign and absolute value of the input
if (input < 0)
{
sgn = -1;
input = -input;
}
else
{
sgn = 1;
}

// Get the integer portion of the input number
trunc = parseInt(input);

// Get the fractional portion of the input
frac = input - trunc;

// Multiply the fractional part by ten to the fifteenth
//    to isolate the 16th digit of the fraction
frac15 = frac * 1000000000000000;

// Discard that 16th digit
frac15t = parseInt(frac15);

// Center the truncated equivalent fraction (tef)
if (frac15t == 499999999999999)
{
frac15t = 500000000000000;
}

// Examine for tef = 0.5 exactly
if (frac15t == 500000000000000)
{
// The tef = 0.5 exactly
// Examine the integer part for even or odd
if(trunc % 2 == 0)
{
// The trunc is even --> round down
output = Math.floor(input);
}
else
{
// The trunc is odd --> round up
output = Math.ceil(input);
}
}
else
{
// The tef is NOT = 0.5 exactly
output = Math.round(input);
}

output = output * sgn;
return output;
}


And here's the function in action, with a comparison of the results of Math.round() and mdjRound() for whichever number you enter:



Results:

For more details on how this all works, just right-click this page and then click on "View Page Source" (in FireFox - other browsers vary slightly but are generally similar).


                                                                                                                                                                M.D.J. 2018/06/08


----------

References:

StackOverFlow. https://stackoverflow.com/questions/18082/validate-decimal-numbers-in-javascript-isnumeric.

Wikipedia Nearest Integer. https://en.wikipedia.org/wiki/Nearest_integer_function.