0

I'm getting error 2.7755575615628914e-17 when I try to add 15 minutes and then subtract 5 minutes 3 times. Should be zero instead. Please help.

http://jsfiddle.net/3zq4napd/

$(document).on('click', '.add', function(event) {
    var input = $('input');

    var inputVal = parseFloat($('input').val());
    var addVal = parseFloat($(this).data('num'));
    var newVal = inputVal + (addVal / 60);

    $(input).val(newVal);
});

$(document).on('click', '.sub', function(event) {
    var input = $('input');

    var inputVal = parseFloat($('input').val());
    var subVal = parseFloat($(this).data('num'));
    var newVal = inputVal - (subVal / 60);

    $(input).val(newVal);
});
Alex G
  • 3,048
  • 10
  • 39
  • 78
  • possible duplicate of [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) –  Sep 30 '14 at 03:34
  • Your problem stems from using floating point maths instead of date & time. See [What every programmer...](http://floating-point-gui.de/) –  Sep 30 '14 at 03:35
  • I don't need to use date & time, when I can use simpler approaches. – Alex G Sep 30 '14 at 03:50
  • Agreed, but trying to patch up floating point arithmetic is a poor option. You'd do better to do all your arithmetic in seconds so that you can use integers throughout, converting only when you display the result. –  Sep 30 '14 at 03:53

1 Answers1

1

That's normal behaviour when dealing with floating point numbers: they can be exactly represented in binary, but not all of them are exactly representable in decimal. Rounding should help.

EDIT: The best way to avoid floating point error is to avoid dealing with numbers that are not exactly representable in binary form - i.e. avoiding any division except by powers of 2. Since 60 is not a power of 2, dividing by 60 will open the door for floating point error. Thus, if you can have your calculation entirely in minutes, or in seconds, or (JavaScript standard) milliseconds, you stay entirely in integral land.

(You could even count in twenty-minute blocks, because your minimal unit is 5 minutes, which is 20 / 2^2, so you're still binary-safe. But if you count in hours (i.e. sixty-minute blocks), there is a further division by 3; since fractions of 3 are not representable in binary, the error pops up.)

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • Rounding makes incorrect values for hours in decimals. – Alex G Sep 30 '14 at 03:35
  • The number is rounded anyway. `1/60` is not really `1/60`, and it is certainly not `0.016666666666666666` (since the actual representation is infinite). The best thing you can do is round it again to a certain number of digits when you want to display it. – Amadan Sep 30 '14 at 03:37
  • Right, but it wont let me do subtraction without math error before I even display. – Alex G Sep 30 '14 at 03:38
  • Even better: don't divide. Divide only when you display. Do everything in minutes. No math error there. – Amadan Sep 30 '14 at 03:39