0

I'm facing an issue, and i would love if some one explains me what is going wrong with my function.

see the code below:

if i run => number(10000.88, 2)

Can anyone explain me why to output 10000.87 instead of 10000.88

where if i run number(11111.88, 2) the output is correct 11111.88 all other outputs are correct.

function number(value, decPos) {
        
  return Math.floor(Math.abs(value) * Math.pow(10, decPos)) / Math.pow(10, decPos);
       
}

document.write("<div>" + number(10, 2) + '</div>');
document.write("<div>" + number(10.8888, 2) + '</div>');
document.write("<div>" + number(100.8888, 2) + '</div>');
document.write("<div>" + number(1000.88, 2) + '</div>');
document.write("<div>" + number(10000.888, 2) + '</div>');
// magic
document.write("<div>" + number(10000.88, 2) + '</div>');

document.write("<div>" + number(100000.8888, 2) + '</div>');

// magic
document.write("<div>" + number(8368.88, 2) + '</div>');

document.write("<div>" + number(11111.8888, 2) + '</div>');
document.write("<div>" + number(11111.88, 2) + '</div>');
<div id="result"></div>
Saif Adnan
  • 307
  • 3
  • 12
  • 1
    Do you realize there is toFixed()? – epascarello Aug 14 '15 at 15:54
  • 1
    possible duplicate of [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – HPierce Aug 14 '15 at 15:54
  • Using toFixed will not fix my issue, because numbers can have not only 2 decimals points, for example (1111.88787).toFixed(2) will equal 1111.89 – Saif Adnan Aug 14 '15 at 15:56
  • I removed the `Math.floor(` and that worked for the first rounding error, because it was dropping the decimal, `10000.88 * 100` returns `1000087.999999` instead of expected `1000088` – mswieboda Aug 14 '15 at 15:57

4 Answers4

1

This is a rounding error, accuracy cannot be guaranteed using doubles or floats.

Hughzi
  • 2,470
  • 1
  • 20
  • 30
1

That's not how rounding works, you would be getting inaccurate numbers.

But if you must:

function subdec(value, decimals)
{
    decimals = decimals || 2;
    var parts = value.toString().split('.');

    if (parts[1]) {
        parts[1] = parts[1].substr(0, decimals);
        return parseFloat(parts.join('.'));
    }

    return value;
}

Add a call to this function to your number () function.

Coffee'd Up Hacker
  • 1,356
  • 11
  • 23
0

You can use this function that generates expected results.

function number(value, decPos) { 
    str = String(value).split(".");
    if (str[1]) {
        return str[0]+"."+str[1].substring(0, decPos);
    }
    return str[0];
}
Mateo Hrastnik
  • 533
  • 1
  • 7
  • 20
0

I adjusted your code a bit so as to take advantage of the .toFixed() function. I made it so the decPos also determines how many decimal places .toFixed() will cut off at. Is this the functionality you’re looking for?

function number(value, decPos) {
        
  return Math.floor((Math.abs(value) * Math.pow(10, decPos)).toFixed(decPos)) / Math.pow(10, decPos);
       
}

document.write("<div>" + number(10, 2) + '</div>');
document.write("<div>" + number(10.8888, 2) + '</div>');
document.write("<div>" + number(100.8888, 2) + '</div>');
document.write("<div>" + number(1000.88, 2) + '</div>');
document.write("<div>" + number(10000.888, 2) + '</div>');
// magic
document.write("<div>" + number(10000.88, 2) + '</div>');

document.write("<div>" + number(100000.8888, 2) + '</div>');

// magic
document.write("<div>" + number(8368.88, 2) + '</div>');

document.write("<div>" + number(11111.8888, 2) + '</div>');
document.write("<div>" + number(11111.88, 2) + '</div>');
document.write("<div>" + number(10000.888, 3) + '</div>');
// magic
document.write("<div>" + number(10000.88, 3) + '</div>');
<div id="result"></div>
Michael
  • 2,016
  • 5
  • 35
  • 51