Dealing with float precision in Javascript

JavascriptFloating PointDoubleFloating AccuracyNumerical Methods

Javascript Problem Overview


I have a large amount of numeric values y in javascript. I want to group them by rounding them down to the nearest multiple of x and convert the result to a string.

How do I get around the annoying floating point precision?

For example:

0.2 + 0.4 = 0.6000000000000001

Two things I have tried:

>>> y = 1.23456789 
>>> x = 0.2 
>>> parseInt(Math.round(Math.floor(y/x))) * x; 
1.2000000000000002

and:

>>> y = 1.23456789 
>>> x = 0.2 
>>> y - (y % x)
1.2000000000000002

Javascript Solutions


Solution 1 - Javascript

From this post: https://stackoverflow.com/questions/1458633/elegant-workaround-for-javascript-floating-point-number-problem

You have a few options:

  • Use a special datatype for decimals, like decimal.js
  • Format your result to some fixed number of significant digits, like this: (Math.floor(y/x) * x).toFixed(2)
  • Convert all your numbers to integers

Solution 2 - Javascript

You could do something like this:

> +(Math.floor(y/x)*x).toFixed(15);
1.2

Edit: It would be better to use big.js.

big.js

> A small, fast, easy-to-use library for arbitrary-precision decimal arithmetic.

>> bigX = new Big(x)
>> bigY = new Big(y)
>> bigY.div(bigX).round().times(bigX).toNumber() // => 1.2

Solution 3 - Javascript

> var x = 0.1
> var y = 0.2
> var cf = 10
> x * y
0.020000000000000004
> (x * cf) * (y * cf) / (cf * cf)
0.02

Quick solution:

var _cf = (function() {
  function _shift(x) {
    var parts = x.toString().split('.');
    return (parts.length < 2) ? 1 : Math.pow(10, parts[1].length);
  }
  return function() { 
    return Array.prototype.reduce.call(arguments, function (prev, next) { return prev === undefined || next === undefined ? undefined : Math.max(prev, _shift (next)); }, -Infinity);
  };
})();

Math.a = function () {
  var f = _cf.apply(null, arguments); if(f === undefined) return undefined;
  function cb(x, y, i, o) { return x + f * y; }
  return Array.prototype.reduce.call(arguments, cb, 0) / f;
};

Math.s = function (l,r) { var f = _cf(l,r); return (l * f - r * f) / f; };

Math.m = function () {
  var f = _cf.apply(null, arguments);
  function cb(x, y, i, o) { return (x*f) * (y*f) / (f * f); }
  return Array.prototype.reduce.call(arguments, cb, 1);
};

Math.d = function (l,r) { var f = _cf(l,r); return (l * f) / (r * f); };

> Math.m(0.1, 0.2)
0.02

You can check the full explanation here.

Solution 4 - Javascript

Check out this link.. It helped me a lot.

http://www.w3schools.com/jsref/jsref_toprecision.asp

The toPrecision(no_of_digits_required) function returns a string so don't forget to use the parseFloat() function to convert to decimal point of required precision.

Solution 5 - Javascript

Tackling this task, I'd first find the number of decimal places in x, then round y accordingly. I'd use:

y.toFixed(x.toString().split(".")[1].length);

It should convert x to a string, split it over the decimal point, find the length of the right part, and then y.toFixed(length) should round y based on that length.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJeroen OomsView Question on Stackoverflow
Solution 1 - JavascriptRusty FausakView Answer on Stackoverflow
Solution 2 - JavascriptphilipvrView Answer on Stackoverflow
Solution 3 - JavascriptHamza AlayedView Answer on Stackoverflow
Solution 4 - JavascriptprahaladpView Answer on Stackoverflow
Solution 5 - JavascriptwhaattView Answer on Stackoverflow